ab.com コミュニティ https://www.activebasic.com/forum/ |
|
N88モードでMP3の再生方法とは? https://www.activebasic.com/forum/viewtopic.php?t=2472 |
ページ 1 / 1 |
作成者: | トモカズ [ 2008年9月06日(土) 05:29 ] |
記事の件名: | N88モードでMP3の再生方法とは? |
N88モードにてMP3ファイルの再生方法をご教授いただけないでしょうか? WAVファイルについては「Win32プログラミング講座 ~ Step29. WAVEファイルを再生する ~」 にて記述されておりますが、WAVだとサイズも大きいのでMP3を扱いたいのです。 次の項「Win32プログラミング講座 ~ Step30. MCIコマンドで音楽ファイルを再生する ~」 にてMP3ファイルの取り扱いについて触れていますが、N88モードにてどのように扱ったらよいのかが分かりません。 希望としては、以下のように使いたいと考えております ・非同期にてファイルを指定すると再生する ・現在再生しているMP3の再生を終了する 例えば以下の様に使用できればと思います。 Playmp3Stop("C:\Winnt\Media\The Microsoft Sound.wav") '再生 '何か別の処理をする Playmp3Sound() '現在再生しているMP3の再生を終了 宜しくお願いいたします。 |
作成者: | トモカズ [ 2008年9月07日(日) 08:06 ] |
記事の件名: | 自己レスです |
「Win32プログラミング講座 ~ Step30. MCIコマンドで音楽ファイルを再生する ~」 のサンプルコードをN88BASICモードとして以下の様に置き換えてみました。 試行錯誤にて、「どうにか、動作出来るレベル」になった程度なので、本来の手法(?)とは違うのだろうなぁと感じています。 「ここはこうすべき」、「この方が効率的」、「ここが変」 などなど、アドバイスをいただけますと幸いです。 よろしくお願いいたします。 #N88BASIC #include <api_mmsys.sbp> Dim I$ AS STRING Dim filename(500) AS BYTE ' ----------------------------------ここから---------------------------------- Dim mop As MCI_OPEN_PARMS *loop Openfile() Playsound() I$=Input$(1) Playstop() goto *loop end ' ----------------------------------ここまで---------------------------------- '↑先頭部分には、MCIデバイスのオープン情報のための構造体を用意します。 Sub Openfile() Dim ofn As OPENFILENAME Dim buffer[MAX_PATH-1] As Byte 'ファイル名を取得 ofn.lStructSize=76 ofn.hwndOwner=_PromptSys_hWnd'hMainWnd ofn.lpstrFilter=Ex"音楽 ファイル(*.wav;*.mid;*.mp3)\0*.wav;*.mid;*.mp3\0すべてのファイル(*.*)\0*\0\0" ofn.nFilterIndex=1 ofn.nMaxFile=MAX_PATH ofn.lpstrFile=buffer GetOpenFileName(ofn) lstrcpy(filename,buffer) End Sub '↑OPENボタンがクリックされたときに呼び出されるイベントです。GetOpenFileName関数でファイル名を取得し、テキストボックス(Static_Path)にファイルパスを表示します。 Sub Playsound() Dim bErr As Long Dim mpp As MCI_PLAY_PARMS Dim buffer[MAX_PATH-1] As Byte '再生中の場合は停止させる If mop.wDeviceID Then Playstop() 'サウンド ファイルのパスを設定します。 mop.lpstrElementName=buffer 'メッセージ通知のためのウィンドウを指定 mop.lpstrElementName=filename mop.dwCallback=_PromptSys_hWnd 'MCIデバイスをオープン bErr=mciSendCommand(0,MCI_OPEN,MCI_OPEN_ELEMENT,mop) If bErr Then MessageBox(_PromptSys_hWnd,"デバイスのオープンに失敗","error",MB_OK) Exit Sub End If '再生 mpp.dwCallback=_PromptSys_hWnd bErr=mciSendCommand(mop.wDeviceID,MCI_PLAY,MCI_NOTIFY,mpp) If bErr Then MessageBox(_PromptSys_hWnd,"デバイスの再生に失敗","error",MB_OK) Exit Sub End If End Sub '↑PLAYボタンがクリックされたときに呼び出されるイベントです。MCI_OPENコマンドでMCIデバイスを開き、MCI_PLAYコマンドでデバイスを再生します。 Sub Playstop() Dim bErr As Long Dim dwCallback As DWord '停止 bErr=mciSendCommand(mop.wDeviceID,MCI_STOP,MCI_WAIT,dwCallback) If bErr Then MessageBox(_PromptSys_hWnd,"デバイスの停止に失敗","error",MB_OK) Exit Sub End If 'デバイスを閉じる mciSendCommand(mop.wDeviceID,MCI_CLOSE,MCI_WAIT,dwCallback) mop.wDeviceID=0 End Sub '↑STOPボタンがクリックされたときに呼び出されるイベントです。MCI_STOPコマンドでデバイスを停止させ、MCI_CLOSEコマンドでデバイスをクローズしています。 Sub MainWnd_MciNotify(flags As Long, DevID As Long) Dim dwCallback As DWord If flags=MCI_NOTIFY_SUCCESSFUL Then 'デバイスを閉じる mciSendCommand(DevID,MCI_CLOSE,MCI_WAIT,dwCallback) mop.wDeviceID=0 MessageBox(_PromptSys_hWnd,"再生終了","Sound test",MB_OK) End If End Sub /* ↑MciNotifyは、再生が終了した場合などにMCIコマンドから送られるイベントです。RADツールの「イベント処理」ダイアログのMMSYSタブで表示されています。 再生が正常に終了した場合(flagsパラメータに MCI_NOTIFY_SUCCESSFUL フラグがセットされていたとき)はMCI_CLOSEコマンドを送り、MCIデバイスをクローズします。DevID変数とmop.wDeviceID変数には同じ値がセットされています。 |
作成者: | トモカズ [ 2008年9月08日(月) 22:49 ] |
記事の件名: | ループ再生について |
上記にて再生は出来たと書きましたが、「MCI_NOTIFY」の取り扱いが理解出来ず、ループ再生 (BGMのように扱いたい) の方法が分かりません。 検討違いの質問かもしれませんが、ご教授の程宜しくお願いいたします。 |
作成者: | NoWest [ 2008年9月09日(火) 01:30 ] |
記事の件名: | Re: ループ再生について |
引用: > 上記にて再生は出来たと書きましたが、「MCI_NOTIFY」の取り扱いが理解出来ず、ループ再生 (BGMのように扱いたい) の方法が分かりません。
> > 検討違いの質問かもしれませんが、ご教授の程宜しくお願いいたします。 トモカズさんがされようとしていることはAB3.X以降のN88BASICモードでの 実装は正攻法では無理だと思います。 勿論、正攻法でできないだけでN88BASIC互換モードの裏側を理解している者に とってはそんなに難しいことではありませんので少し時間を頂ければ ループ再生のサンプルをのせたいと思います。 |
作成者: | NoWest [ 2008年9月09日(火) 05:38 ] |
記事の件名: | |
ということでサンプルできましたのでのせときます。 ソースはこちら [ここをクリックすると内容が表示されます]
コード: #N88BASIC #include <api_mmsys.sbp> '----------------オマジナイ----------------- Dim proc As DWord proc = SetWindowLong(_PromptSys_hWnd,GWL_WNDPROC,AddressOf(MyCallback)) '------------------------------------------- 'ウィンドウメッセージ Const WM_MCIOPEN = WM_USER + 1 Const WM_MCICLOSE = WM_USER + 2 Const WM_MCIPLAY = WM_USER + 3 Const WM_MCISTOP = WM_USER + 4 '構造体の準備 Dim mop As MCI_OPEN_PARMS Dim mpp As MCI_PLAY_PARMS 'MCIデバイスを開く Dim device1 As Long device1 = SendMessage(_PromptSys_hWnd,WM_MCIOPEN,"waveaudio","C:\WINDOWS\Media\Windows XP Startup.wav") Dim device2 As Long device2 = SendMessage(_PromptSys_hWnd,WM_MCIOPEN,"waveaudio","C:\WINDOWS\Media\notify.wav") 'device1をループ再生 SendMessage(_PromptSys_hWnd,WM_MCIPLAY,device1,MCI_NOTIFY) 'device2を1秒おきに10回再生 Dim cnt As Long For cnt = 1 To 10 SendMessage(_PromptSys_hWnd,WM_MCIPLAY,device2,0) Sleep(1000) Next 'MCIデバイスを閉じる SendMessage(_PromptSys_hWnd,WM_MCICLOSE,device1,0) device1 = 0 SendMessage(_PromptSys_hWnd,WM_MCICLOSE,device2,0) device2 = 0 End '--------------------コールバック関数--------------------------------------------------- Function MyCallback(hWnd As HWND, Msg As DWord, wParam As WPARAM, lParam As LPARAM) As LRESULT Select Case Msg Case WM_DESTROY '必ず実装してください。 'プログラムの終了時に開いたままのデバイスを必ずここで全て閉じること! '複数のBGMやサウンドを再生する場合はdeviceを配列にしてくといいかも。 If device1 <> 0 Then mciSendCommand(device1,MCI_CLOSE,MCI_WAIT,hWnd) If device2 <> 0 Then mciSendCommand(device2,MCI_CLOSE,MCI_WAIT,hWnd) Case WM_MCIOPEN 'デバイスを開く処理 mop.lpstrDeviceType = wParam mop.lpstrElementName = lParam mop.dwCallback = _PromptSys_hWnd mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE or MCI_OPEN_ELEMENT,mop) MyCallback = mop.wDeviceID Exit Function Case WM_MCICLOSE 'MCIデバイスを閉じる処理 mciSendCommand(wParam,MCI_CLOSE,MCI_WAIT,hWnd) MyCallback = 0 Exit Function Case WM_MCIPLAY 'MCIデバイスを再生する処理 mpp.dwCallback = hWnd mpp.dwFrom = 0 mciSendCommand(wParam,MCI_PLAY,lParam or MCI_FROM,mpp) MyCallback = 0 Exit Function Case WM_MCISTOP 'MCIデバイスを停止する処理 mciSendCommand(wParam,MCI_STOP,MCI_WAIT,hWnd) MyCallback = 0 Exit Function Case MM_MCINOTIFY 'MCI_NOTIFYの処理 Select Case wParam Case MCI_NOTIFY_SUCCESSFUL mpp.dwCallback = hWnd mpp.dwFrom = 0 'MCIデバイスの再生(notifyを指定しているのでループ再生になる) mciSendCommand(wParam,MCI_PLAY,MCI_FROM or MCI_NOTIFY,mpp) End Select End Select MyCallback = CallWindowProc(proc,hWnd,Msg,wParam,lParam) End Function 肝心のMP3の再生ですが、"waveaudio"の部分を"mpegvideo"にすれば再生できるはずです。 内容的に難しくなってしまったので分からないことがあれば質問してください。 |
作成者: | トモカズ [ 2008年9月12日(金) 09:53 ] |
記事の件名: | 試行錯誤しています。 |
NoWestさん、早々にサンプログラムまで作成していただき、ありがとうございます。 N88モードでは、そもそも正攻法では出来なかったのですね。 さて、サンプルプログラムを色々と自分なりに(使い方を)理解しようと 試してみました。 サンプルをベースに簡易的に、手を入れて自分なりのサンプルを色々作成してみました。(Device1を途中で止める・・・だとか、ここでDvice2を再生するだとか・・・試してみました) とりあえず、扱い方は理解したので(と思います)、自分のソフトに実装してみました。 「思った通りの動作をした」・・・と思いきや、暫く実行していると、強制終了してしまいました。 その後も、MICデバイスを開くタイミングだとかMICデバイスを閉じるタイミングなど変更して試しています。 それでも、未だに正常に動作しないのですが、(Device1がループ再生しているかと思いきや4~5回再生すると終了してしまったり・・・) 私の実装方法に問題があると思いますので、もうちょっと頑張ってみます。 (自作簡易サンプルだとうまく動作するのに、それと同様に組み込んでるんですけどね・・) |
作成者: | NoWest [ 2008年9月15日(月) 16:39 ] |
記事の件名: | Re: 試行錯誤しています。 |
引用: > N88モードでは、そもそも正攻法では出来なかったのですね。
AB2.Xの頃はMCISound命令というのが実装されていまして> さて、サンプルプログラムを色々と自分なりに(使い方を)理解しようと > 試してみました。 こいつを使ってMCIを操作していたんですが、AB3.X系からは実装されていません。 引用: > 「思った通りの動作をした」・・・と思いきや、暫く実行していると、強制終了してしまいました。
何が問題なのかもう少し具体的な情報がないと判断できません。> その後も、MICデバイスを開くタイミングだとかMICデバイスを閉じるタイミングなど変更して試しています。 > > それでも、未だに正常に動作しないのですが、(Device1がループ再生しているかと思いきや4~5回再生すると終了してしまったり・・・) > 私の実装方法に問題があると思いますので、もうちょっと頑張ってみます。 > (自作簡易サンプルだとうまく動作するのに、それと同様に組み込んでるんですけどね・・) OSは? ABのバージョンは? プログラムの流れは? 何が問題なのか整理をつけながらデバックするとよいでしょう。 私が良く使う手はプログラムの同一機能の部分を「'」コメントアウトして プログラムの全体に問題点がないかを探しておき、 今度は細かな部分を徐々に確認していきます。 今回のサンプルで言えば、 1.まずはMCIに関するAPI関連部分を全てコメントアウトして MCIの再生部分以外に問題がないことを確認します。 2.続いてMCIデバイスを開く部分と閉じる部分のコメントアウトを外し 確実に開かれたデバイスが閉じられているかを確認します。 3.最後にその他の機能を少しずつ回復させながらデバックを行います。 全体を通していえますが、コメントアウトを外しながらその部分を記述を 確認しましょう。引数を間違えるとか大ポカをやらかしていることも多々あります。 あとはGetLastError関数とmciGetErrorString関数を使うのも手ですね。 コイツを使うとエラーの詳細情報を得られます。 |
作成者: | トモカズ [ 2010年4月25日(日) 07:26 ] |
記事の件名: | 約1年半が経過 |
NoWestさん、ありがとうございました。 約1年半が経過してしまいましたが、ようやく解決いたしました。 全然、分からなくって半ば諦めかけていました。 > 「思った通りの動作をした」・・・と思いきや、暫く実行していると、強制終了してしまいました。 MP3のループ再生のプログラムを実装すると、確かにこのような症状になるのですが、 原因は (なのかどうかは、定かではありませんが・・・) 文字列変数(String)を多用していたからだったのかもしれません。 これを修正したら、強制終了が起こる事は一切無くなりました。 String多用であっても、MP3再生をしなければ強制終了が起こらないというのも謎です。 文字列変数を使うと不安定になるのでしょうか? |
ページ 1 / 1 | 全ての表示時間は UTC+09:00 です |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |