最初音を鳴らすと、ボリュームが「0」なのに音がでてしまう – プログラミング – Home

最初音を鳴らすと、ボリュームが「0」な...
 
通知
すべてクリア

[解決済] 最初音を鳴らすと、ボリュームが「0」なのに音がでてしまう

固定ページ 1 / 2

けじゅ
 けじゅ
(@けじゅ)
ゲスト
結合: 22年前
投稿: 26
Topic starter  

おせわになっています。けじゅです。

「スライダーを2つ配置すると、コンパイルはできるが実行されない」
とう内容の続きで、新たな問題が発生しました。
スライダーをボリュームの変わりに使っていますが。最初音を鳴らすと、ボリュームが
「0」なのに音がでてしまいます。スライダーをクリックすると音は0になり、上にド
ラッグしてくと音は大きくなります。最初0なのに音をでなくするにはどうしたらよい
のでしょうか?

環境は VC++6.0 MFC windowXP です。 


引用未解決
トピックタグ
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

あなたがどんなコードを書いているのかわからないのでアドバイスのしようがありませ
ん。
せめてサウンドを再生しているところのコードくらい載せてくださいな


返信引用
セル
 セル
(@セル)
ゲスト
結合: 22年前
投稿: 4
 

すみませんシャノンさん 関係しているところをのせました。
①は、マウスがスライダーをコントロールするためのクラスです。
②は、音量を調整する関数です
③は、MIDIでメロディーを出力する関数です
④はボタンを押したときにMIDIで「ファ」を出力するクラスです。

今回④を実行したときにスライダーの音量は「0」なのに、最初音が出てしまいます。
そしてスライダーをクリックすると音はきえます。最初から音量が0になる方法をおし
えてください。

//①
void CVcdoremiDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{

int x,y;
UpdateData(TRUE);

x=m_sldr.GetPos();
y=m_sldr1.GetPos();
volume(x);
//pan(y);
UpdateData(FALSE);

CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

//②
void volume(int x)
{

MMRESULT ret;
DWORD dwMsg;
x=127-x;
dwMsg = 0x0007B0+ x* 0x10000;
ret = midiOutShortMsg(hMidiOut, dwMsg);

}

//③
void midi_play(int doremi) //ドレミを出す
{
MMRESULT ret;
DWORD dwMsg;

dwMsg = 0x7F3C90 + doremi * 0x100; //オン
ret = midiOutShortMsg(hMidiOut, dwMsg);

}

//④
void CVcdoremiDlg ::OnButton4() // [ふぁ]
{

midi_play(5);
}


返信引用
けじゅ
 けじゅ
(@けじゅ)
ゲスト
結合: 22年前
投稿: 26
Topic starter  

セル=けじゅ  です。


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

プログラム起動時に volume が呼ばれてないため、最初はスライダーが 0 というのがボ
リュームに反映されてないせいだと思われます。
OnInitDialog で volume を呼んでやりませう。


返信引用
けじゅ
 けじゅ
(@けじゅ)
ゲスト
結合: 22年前
投稿: 26
Topic starter  

OnInitDialog()の所にm_sldr.GetPos();とvoid volume();を追加しましたが変化なっか
たです。ボタンをおしてMIDIの音を鳴らすとスライダーの位置は0なのに音がでてしまい
う。ボタンを押す前にスライダーをクリックすれば、音は出ない。
アドバイスおねがいします。

BOOL CVcdoremiDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// バージョン情報... メニュー項目をシステム メニューへ追加します。

// IDM_ABOUTBOX はコマンド メニューの範囲でなければなりません。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX,
strAboutMenu);
}
}

// このダイアログ用のアイコンを設定します。フレームワークはアプリケー
ションのメイン
// ウィンドウがダイアログでない時は自動的に設定しません。
SetIcon(m_hIcon, TRUE); // 大きいアイコンを設定
SetIcon(m_hIcon, FALSE); // 小さいアイコンを設定

// TODO: 特別な初期化を行う時はこの場所に追加してください。
m_sldr.SetRange(0,127);
m_sldr.SetTicFreq(10);
m_sldr.SetPageSize(5);
m_sldr.SetLineSize(20);
m_sldr.SetPos(127);
m_sldr.GetPos();
void volume();
if(midi_set()==0) EndDialog(IDCANCEL); //■追加

return TRUE; // TRUE を返すとコントロールに設定したフォーカスは失われ
ません。
}


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

キツい口調になってしまうことを最初にお詫びしておきます。

確かに私は
>OnInitDialog で volume を呼んでやりませう。
と言いましたが、あなたはご自分の書いた
>m_sldr.GetPos();
>void volume();
このコードの意味を理解してらっしゃいますか?

GetPos で取得した値はどこにも保存されていませんし、volume には有効な値が渡され
ていません。さて、この2行にどれほどの意味があるんでしょうか…

惜しいところまで行ってます。
敢えて解答は書きませんので、もう少し頑張ってみてください。


返信引用
けじゅ
 けじゅ
(@けじゅ)
ゲスト
結合: 22年前
投稿: 26
Topic starter  

お世話になっています。
シャノンさん「OnInitDialog」のところに下記のように書きましたが ビルドして実行
してみましたが、変化ないです。 宜しくお願いします。

int x;
x=m_sldr.GetPos( );
void volume(int x);


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

>void volume(int x);
なんかツッコミたくなりますが、まぁ写しミスでしょうかね。
そうするってぇと…しばしお待ちを。
こっちでも同じプログラムを組んで試してみるとしましょう


返信引用
wood
 wood
(@wood)
ゲスト
結合: 24年前
投稿: 895
 

hMidiOutは取得しなくて良いものなのですか?
どこかのヘッダに固定値入っているの?

volumeのところのmidiOutShortMsg戻り値は正常に
「MMSYSERR_NOERROR」になってますか

ちょっと気になること
>void volume(int x);
関数呼び出すのに一々「void」っているの?

MIDIデバイスって初期化のいないデバイスなの?

> if(midi_set()==0) EndDialog(IDCANCEL); //■追加
これって何のための処理なの?


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

思うにMFCで組んだ時にそれぞれのメッセージハンドラが
どういうタイミング呼ばれるか、どういう順番でコールされていくか
と言った部分が良く理解できていないような気がします。

この辺の部分がわからない状態で行き当たりばったりにプログラムを組んでも
結局、自分の首を絞めるだけです。
メッセージハンドラがどんなタイミングで呼ばれているかを確認するだけなら
簡単なテストアプリを作ってTRACE文を入れてみるとか、デバッガーで止めてみるとか
すれば、簡単に確認できるので自分で実践される事をお勧めします。

今回の場合、ボリュームの初期設定をしていないのが原因ですが、
初期設定が必要なのはわかっているのだけれど、どこで書いて良いのかわからないのと
初期設定が必要な事自体がわかっていないのとでは雲泥の差があります。

基本的にプログラムは自分で書いた処理しか走りません。
問題なのはMFCでカプセルかされてしまって表に出てこないけれど、処理されている
部分でしょうねぇ。多分、はじめたばかり人はMFCで勝手にやってくれる部分と
自分でコードを書かねばならない部分の区切りが良く理解できないのでしょうね。

この辺って、Win32SDKでプログラミングした事が無いとわからないかもしれないですね。
どの辺までがWindowsプログラミングの定型的な部分で、
どの辺までが作成者に任されている部分なのかとか。


返信引用
aetos
(@aetos)
Noble Member
結合: 6年前
投稿: 1480
 

似たようなアプリを作ってみましたが、ちゃんと音量が最小の時は音が出ないようにな
ってますよ。

>hMidiOutは取得しなくて良いものなのですか?
>どこかのヘッダに固定値入っているの?
>MIDIデバイスって初期化のいないデバイスなの?

たしかに初期化するコードは入っていませんが、音は出ているようですからここに書い
てないだけで初期化はしてるんじゃないでしょうか。…しててくださいよ。

>「OnInitDialog」のところに下記のように書きましたが
>x=m_sldr.GetPos( );

この戻り値がちゃんと 127 になっていますか?


返信引用
けじゅ
 けじゅ
(@けじゅ)
ゲスト
結合: 22年前
投稿: 26
Topic starter  

ありがとうございます。シャノンさん、一つチェックしてほしいことがありますが、
アプリを実行したら、最初に音をならすボタンを押したら鳴りますでしょか?何回かためしても
らえないでしょうか? いつもいろいろなアドバイスありがとうございます。


返信引用
PATIO
(@patio)
Famed Member
結合: 4年前
投稿: 2660
 

シャノンさんが作ってくれたのは、似たようなアプリであって
けじゅさんが作ったアプリと同じものではないわけなので
シャノンさんのアプリで試しても意味が無いと思いますよ。
あなたが書いたコードと全く同じコードではないと思いますし。

あと、コード的に以下の部分は無駄だと思います。
m_sldr.SetPos(127);
x = m_sldr.GetPos();
volume(x);

初期値を定数定義して以下のようにした方がすっきりします。
static const int sciInitVolume = 127;

m_sldr.SetPos(sciInitVolume);
volume(sciInitVolume);

スライダーコントロールのGetPosを呼ぶ意味が無いです。
値はわかっているわけなのでそのまま設定すれば良いだけです。
あと、数値を直接プログラムに埋め込むのはやめて定数定義を使いましょう。
C++言語の入門書にこの辺の説明があるはずです。
急がば回れとも言います。基礎を固めた方があとあと役に立ちます。


返信引用
wood
 wood
(@wood)
ゲスト
結合: 24年前
投稿: 895
 

MIDIデバイスの初期化処理をどこでどのように行っているか明確に
答えてもらってないのですが?
私の言いたいことは

> if(midi_set()==0) EndDialog(IDCANCEL); //■追加
が初期化処理してませんかと言うことです
この行以前までの関数呼び出しに対してそれぞれ成功ステータスが返って
きていれば何らかの状況変化が望めると思います
なんら変化が見れないのであれば、それを無効化しているものが存在するはずです


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました