パソコンが再生している音楽を録音
返信@yu0627
> > 教えてくださりありがとうございます。動作確認できました。
> > これからは色々と自分で試行錯誤してみます。もし乗り越えれない壁に当たったらまた返信するかもしれません。
> > ちなみに僕の環境で44100KHz 16bit Stereoで録音するとやばくなります。再生速度が遅いというか...。
>
>
> たぶんバッファサイズを大きくとれば改善するでしょう。
> このサンプルでは1*1024bitいわゆる1Kbyteですが
> 6K~8K位に増やせばCPUの遅いパソコンでも大丈夫だと思います。
ありがとうございます。5KBにバッファを増やしたらうまく動くようになりました。
WinXP Home SP2
AMD AthlonXP 1700+ (1.46GHz)
384MB
↑この環境でもこうなりました...。
> > これからは色々と自分で試行錯誤してみます。もし乗り越えれない壁に当たったらまた返信するかもしれません。
> > ちなみに僕の環境で44100KHz 16bit Stereoで録音するとやばくなります。再生速度が遅いというか...。
>
>
> たぶんバッファサイズを大きくとれば改善するでしょう。
> このサンプルでは1*1024bitいわゆる1Kbyteですが
> 6K~8K位に増やせばCPUの遅いパソコンでも大丈夫だと思います。
ありがとうございます。5KBにバッファを増やしたらうまく動くようになりました。
WinXP Home SP2
AMD AthlonXP 1700+ (1.46GHz)
384MB
↑この環境でもこうなりました...。
[最重要]
久しぶりにWAVE関連のプログラムを弄っていたら
私の書き込んだソースに欠陥を発見しました。
このソースを使ってプログラムを作っていた方は修正してください。
修正箇所はウィンドウのDESTROYイベント内にあります。
私の書き込んだソースに欠陥を発見しました。
このソースを使ってプログラムを作っていた方は修正してください。
修正済みコード [ここをクリックすると内容が表示されます]
コード: 全て選択
'-----------------------------------------------------------------------------
' イベント プロシージャ
'-----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd
' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。
Const MAXPNAMELEN = 32
Const MAXERRORLENGTH = 256
Const MAX_JOYSTICKOEMVXDNAME = 260
Const MMSYSERR_NOERROR = 0
Const MM_WOM_OPEN = &H3BB
Const MM_WOM_CLOSE = &H3BC
Const MM_WOM_DONE = &H3BD
Const MM_WIM_OPEN = &H3BE
Const MM_WIM_CLOSE = &H3BF
Const MM_WIM_DATA = &H3C0
Const CALLBACK_WINDOW = &H00010000
TypeDef HWAVEIN = DWord
TypeDef HWAVEOUT = DWord
Const WAVE_MAPPER = -1
Type WAVEINCAPS
wMid As Word
wPid As Word
vDriverVersion As DWord
szPname[ELM(MAXPNAMELEN)] As Byte
dwFormats As DWord
wChannels As Word
wReserved1 As Word
End Type
Const WAVE_INVALIDFORMAT = &H00000000
Const WAVE_FORMAT_1M08 = &H00000001
Const WAVE_FORMAT_1S08 = &H00000002
Const WAVE_FORMAT_1M16 = &H00000004
Const WAVE_FORMAT_1S16 = &H00000008
Const WAVE_FORMAT_2M08 = &H00000010
Const WAVE_FORMAT_2S08 = &H00000020
Const WAVE_FORMAT_2M16 = &H00000040
Const WAVE_FORMAT_2S16 = &H00000080
Const WAVE_FORMAT_4M08 = &H00000100
Const WAVE_FORMAT_4S08 = &H00000200
Const WAVE_FORMAT_4M16 = &H00000400
Const WAVE_FORMAT_4S16 = &H00000800
Const WAVE_FORMAT_PCM = 1
Type WAVEHDR
lpData As *Byte
dwBufferLength As DWord
dwBytesRecorded As DWord
dwUser As DWord
dwFlags As DWord
dwLoops As DWord
lpNext As VoidPtr
reserved As DWord
End Type
Type WAVEFORMAT
wFormatTag As Word
nChannels As Word
nSamplesPerSec As DWord
nAvgBytesPerSec As DWord
nBlockAlign As Word
End Type
Type PCMWAVEFORMAT
wf As WAVEFORMAT
wBitsPerSample As Word
End Type
Type WAVEFORMATEX
wFormatTag As Word
nChannels As Word
nSamplesPerSec As DWord
nAvgBytesPerSec As DWord
nBlockAlign As Word
wBitsPerSample As Word
cbSize As Word
End Type
Declare Function waveOutOpen Lib "WINMM" (ByRef phwo As HWAVEOUT, uDeviceID As DWord, ByRef pwfx As WAVEFORMATEX, dwCallback As DWord, dwInstance As DWord, fdwOpen As DWord) As DWord
Declare Function waveOutClose Lib "WINMM" (hwo As HWAVEOUT) As DWord
Declare Function waveOutPrepareHeader Lib "WINMM" (hwo As HWAVEOUT, ByRef pwh As WAVEHDR, cbwh As DWord) As DWord
Declare Function waveOutUnprepareHeader Lib "WINMM" (hwo As HWAVEOUT, ByRef pwh As WAVEHDR, cbwh As DWord) As DWord
Declare Function waveOutWrite Lib "WINMM" (hwo As HWAVEOUT, ByRef pwh As WAVEHDR, cbwh As DWord) As DWord
Declare Function waveOutReset Lib "WINMM" (hwo As HWAVEOUT) As DWord
Declare Function waveInGetDevCaps Lib "WINMM" Alias "waveInGetDevCapsA" (uDeviceID As DWord, ByRef pwic As WAVEINCAPS, cbwic As DWord) As DWord
Declare Function waveInOpen Lib "WINMM" (ByRef phwi As HWAVEIN, uDeviceID As DWord, ByRef pwfx As WAVEFORMATEX, dwCallback As DWord, dwInstance As DWord, fdwOpen As DWord) As DWord
Declare Function waveInClose Lib "WINMM" (hwi As HWAVEIN) As DWord
Declare Function waveInPrepareHeader Lib "WINMM" (hwi As HWAVEIN, ByRef pwh As WAVEHDR, cbwh As DWord) As DWord
Declare Function waveInUnprepareHeader Lib "WINMM" (hwi As HWAVEIN, ByRef pwh As WAVEHDR, cbwh As DWord) As DWord
Declare Function waveInAddBuffer Lib "WINMM" (hwi As HWAVEIN, ByRef pwh As WAVEHDR, cbwh As DWord) As DWord
Declare Function waveInStart Lib "WINMM" (hwi As HWAVEIN) As DWord
Declare Function waveInReset Lib "WINMM" (hwi As HWAVEIN) As DWord
TypeDef HMMIO = DWord
Const MMIO_RWMODE = &H00000003
Const MMIO_SHAREMODE = &H00000070
Const MMIO_CREATE = &H00001000
Const MMIO_PARSE = &H00000100
Const MMIO_DELETE = &H00000200
Const MMIO_EXIST = &H00004000
Const MMIO_ALLOCBUF = &H00010000
Const MMIO_GETTEMP = &H00020000
Const MMIO_DIRTY = &H10000000
Const MMIO_READ = &H00000000
Const MMIO_WRITE = &H00000001
Const MMIO_READWRITE = &H00000002
Const MMIO_COMPAT = &H00000000
Const MMIO_EXCLUSIVE = &H00000010
Const MMIO_DENYWRITE = &H00000020
Const MMIO_DENYREAD = &H00000030
Const MMIO_DENYNONE = &H00000040
Const MMIO_FHOPEN = &H0010
Const MMIO_EMPTYBUF = &H0010
Const MMIO_TOUPPER = &H0010
Const MMIO_INSTALLPROC = &H00010000
Const MMIO_GLOBALPROC = &H10000000
Const MMIO_REMOVEPROC = &H00020000
Const MMIO_UNICODEPROC = &H01000000
Const MMIO_FINDPROC = &H00040000
Const MMIO_FINDCHUNK = &H0010
Const MMIO_FINDRIFF = &H0020
Const MMIO_FINDLIST = &H0040
Const MMIO_CREATERIFF = &H0020
Const MMIO_CREATELIST = &H0040
TypeDef HMMIO = DWord
TypeDef HTASK = DWord
Type MMIOINFO
dwFlags As DWord
fccIOProc As DWord
pIOProc As DWord
wErrorRet As DWord
htask As HTASK
cchBuffer As Long
pchBuffer As BytePtr
pchNext As BytePtr
pchEndRead As BytePtr
pchEndWrite As BytePtr
lBufOffset As Long
lDiskOffset As Long
adwInfo[ELM(3)] As DWord
dwReserved1 As DWord
dwReserved2 As DWord
hmmio As HMMIO
End Type
Type MMCKINFO
ckid As DWord
cksize As DWord
fccType As DWord
dwDataOffset As DWord
dwFlags As DWord
End Type
Declare Function mmioStringToFOURCC Lib "WINMM" Alias "mmioStringToFOURCCA" (sz As BytePtr, uFlags As DWord) As DWord
Declare Function mmioOpen Lib "WINMM" Alias "mmioOpenA" (pszFileName As BytePtr, ByRef pmmioinfo As MMIOINFO, fdwOpen As DWord) As HMMIO
Declare Function mmioClose Lib "WINMM" (hmmio As HMMIO, fuClose As DWord) As DWord
Declare Function mmioRead Lib "WINMM" (hmmio As HMMIO, pch As BytePtr, cch As Long) As Long
Declare Function mmioWrite Lib "WINMM" (hmmio As HMMIO, pch As BytePtr, cch As Long) As Long
Declare Function mmioDescend Lib "WINMM" (hmmio As HMMIO, ByRef pmmcki As MMCKINFO, ByRef pmmckiParent As MMCKINFO, fuDescend As DWord) As DWord
Declare Function mmioAscend Lib "WINMM" (hmmio As HMMIO, ByRef pmmcki As MMCKINFO, fuAscend As DWord) As DWord
Declare Function mmioCreateChunk Lib "WINMM" (hmmio As HMMIO, ByRef pmmcki As MMCKINFO, fuCreate As DWord) As DWord
'=================================================================================================================
Dim Play_Flag As DWord
Dim Record_Flag As DWord
Dim Stop_Flag As DWord
Const NumOfBuffers = 5 'バッファ数
Const BufferLength = 1*1024 'バッファ長
Dim hWaveIn As HWAVEIN
Dim hWaveOut As HWAVEOUT
Dim WaveHdr[ELM(NumOfBuffers)] As WAVEHDR
Dim WaveOutFormatEx As WAVEFORMATEX
Dim WaveInFormatEx As WAVEFORMATEX
Dim hMmio As HMMIO
Dim MmioInfo As MMIOINFO
Dim MmioCkInfo As MMCKINFO
Dim MmioCkInfoSub As MMCKINFO
Dim WaveData[ELM(NumOfBuffers)] As *Byte
/*************メニューID**************/
Const IDM_1M08 = 100
Const IDM_1S08 = 101
Const IDM_1M16 = 102
Const IDM_1S16 = 103
Const IDM_2M08 = 104
Const IDM_2S08 = 105
Const IDM_2M16 = 106
Const IDM_2S16 = 107
Const IDM_4M08 = 108
Const IDM_4S08 = 109
Const IDM_4M16 = 110
Const IDM_4S16 = 111
/*******WAVE入力デバイスの性能を取得する。********/
Dim WaveInCaps As WAVEINCAPS
waveInGetDevCaps(WAVE_MAPPER,WaveInCaps,SizeOf(WAVEINCAPS))
Dim hMenuSub1 As HMENU
hMenuSub1 = CreatePopupMenu()
If WaveInCaps.dwFormats And WAVE_FORMAT_4S16 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"44100Hz 16bit Stereo",IDM_4S16,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_4M16 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"44100Hz 16bit Mono",IDM_4M16,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_4S08 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"44100Hz 8bit Stereo",IDM_4S08,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_4M08 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"44100Hz 8bit Mono",IDM_4M08,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_2S16 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"22050Hz 16bit Stereo",IDM_2S16,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_2M16 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"22050Hz 16bit Mono",IDM_2M16,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_2S08 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"22050Hz 8bit Stereo",IDM_2S08,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_2M08 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"22050Hz 8bit Mono",IDM_2M08,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_1S16 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"11025Hz 16bit Stereo",IDM_1S16,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_1M16 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"11025Hz 16bit Mono",IDM_1M16,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_1S08 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"11025Hz 8bit Stereo",IDM_1S08,0,0
If WaveInCaps.dwFormats And WAVE_FORMAT_1M08 Then InsMenu hMenuSub1,0,MF_BYPOSITION,"11025Hz 8bit Mono",IDM_1M08,0,0
Dim hMenu As HMENU
hMenu = CreateMenu()
InsMenu hMenu,0,MF_BYPOSITION,"Quality(&Q)",0,hMenuSub1,0
'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数
Function MainWndProc(hWnd As DWord, dwMsg As DWord, wParam As DWord, lParam As DWord) As DWord
' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
Dim cnt As Long
Dim ret As Long
Dim pwh As *WAVEHDR
Select Case dwMsg
Case MM_WOM_OPEN /******WAVE出力デバイスが開かれた時に呼ばれる******/
/******dataチャンクにアクセス******/
MmioCkInfoSub.ckid = mmioStringToFOURCC("data",0)
mmioDescend(hMmio,MmioCkInfoSub,MmioCkInfo,MMIO_FINDCHUNK)
For cnt=0 To NumOfBuffers-1
ret = mmioRead(hMmio,WaveData[cnt],BufferLength)
If ret = 0 or ret = -1 Then
WaveHdr[cnt].dwBufferLength = 0
WaveHdr[cnt].dwUser = TRUE
Else
WaveHdr[cnt].dwBufferLength = ret
WaveHdr[cnt].dwUser = FALSE
End If
waveOutPrepareHeader(hWaveOut,WaveHdr[cnt],SizeOf(WAVEHDR))
Next
For cnt=0 To NumOfBuffers-1
waveOutWrite(hWaveOut,WaveHdr[cnt],SizeOf(WAVEHDR))
Next
EnableWindow(GetDlgItem(hMainWnd,CommandButton1),FALSE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton2),FALSE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton3),TRUE)
Case MM_WOM_CLOSE /******WAVE出力デバイスが閉じられる時に呼ばれる******/
For cnt=0 To NumOfBuffers-1
waveOutUnprepareHeader(hWaveOut,WaveHdr[cnt],SizeOf(WAVEHDR))
Next
EnableWindow(GetDlgItem(hMainWnd,CommandButton1),TRUE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton2),TRUE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton3),FALSE)
Play_Flag = FALSE
Case MM_WOM_DONE /******WAVE出力デバイスのバッファの再生終了時に呼ばれる******/
pwh=lParam
If pwh->dwUser = TRUE or Stop_Flag = TRUE Then
mmioAscend(hMmio,MmioCkInfoSub,0)
mmioClose(hMmio,0)
waveOutClose(hWaveOut)
Stop_Flag = FALSE
Else
/******dataデータを読み込み******/
FillMemory(pwh->lpData,BufferLength,127)
ret = mmioRead(hMmio,pwh->lpData,BufferLength)
If ret = 0 or ret = -1 Then
pwh->dwUser = TRUE
pwh->dwBufferLength = 0
Else
pwh->dwUser = FALSE
pwh->dwBufferLength = ret
End If
waveOutWrite(hWaveOut,ByVal pwh,SizeOf(WAVEHDR))
End If
Case MM_WIM_OPEN /******WAVE入力デバイスが開かれた時に呼ばれる******/
/******dataチャンクを作成******/
MmioCkInfoSub.ckid = mmioStringToFOURCC("data",0)
mmioCreateChunk(hMmio,MmioCkInfoSub,0)
For cnt=0 To NumOfBuffers-1
WaveHdr[cnt].dwUser = FALSE
WaveHdr[cnt].dwBufferLength = BufferLength
waveInPrepareHeader(hWaveIn,WaveHdr[cnt],SizeOf(WAVEHDR))
waveInAddBuffer(hWaveIn,WaveHdr[cnt],SizeOf(WAVEHDR))
Next
waveInStart(hWaveIn)
EnableWindow(GetDlgItem(hMainWnd,CommandButton1),FALSE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton2),FALSE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton3),TRUE)
Case MM_WIM_CLOSE /******WAVE入力デバイスが閉じられる時に呼ばれる******/
For cnt=0 To NumOfBuffers-1
waveInUnprepareHeader(hWaveIn,WaveHdr[cnt],SizeOf(WAVEHDR))
Next
EnableWindow(GetDlgItem(hMainWnd,CommandButton1),TRUE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton2),TRUE)
EnableWindow(GetDlgItem(hMainWnd,CommandButton3),FALSE)
Record_Flag = FALSE
Case MM_WIM_DATA /******WAVE入力デバイスのバッファが一杯になった時に呼ばれる******/
pwh=lParam
If Stop_Flag = TRUE Then
mmioWrite(hMmio,pwh->lpData,pwh->dwBytesRecorded)
mmioAscend(hMmio,MmioCkInfoSub,0)
mmioAscend(hMmio,MmioCkInfo,0)
mmioClose(hMmio,0)
waveInClose(hWaveIn)
Stop_Flag = FALSE
Else
/******dataデータを書き込み******/
mmioWrite(hMmio,pwh->lpData,pwh->dwBytesRecorded)
FillMemory(pwh->lpData,BufferLength,127)
waveInAddBuffer(hWaveIn,ByVal pwh,SizeOf(WAVEHDR))
End If
Case WM_COMMAND
Select Case LOWORD(wParam)
Case IDM_1M08
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_1M08,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 1
WaveInFormatEx.nSamplesPerSec = 11025
WaveInFormatEx.wBitsPerSample = 8
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_1S08
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_1S08,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 2
WaveInFormatEx.nSamplesPerSec = 11025
WaveInFormatEx.wBitsPerSample = 8
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_1M16
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_1M16,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 1
WaveInFormatEx.nSamplesPerSec = 11025
WaveInFormatEx.wBitsPerSample = 16
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_1S16
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_1S16,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 2
WaveInFormatEx.nSamplesPerSec = 11025
WaveInFormatEx.wBitsPerSample = 16
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_2M08
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_2M08,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 1
WaveInFormatEx.nSamplesPerSec = 22050
WaveInFormatEx.wBitsPerSample = 8
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_2S08
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_2S08,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 2
WaveInFormatEx.nSamplesPerSec = 22050
WaveInFormatEx.wBitsPerSample = 8
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_2M16
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_2M16,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 1
WaveInFormatEx.nSamplesPerSec = 22050
WaveInFormatEx.wBitsPerSample = 16
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_2S16
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_2S16,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 2
WaveInFormatEx.nSamplesPerSec = 22050
WaveInFormatEx.wBitsPerSample = 16
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_4M08
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_4M08,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 1
WaveInFormatEx.nSamplesPerSec = 44100
WaveInFormatEx.wBitsPerSample = 8
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_4S08
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_4S08,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 2
WaveInFormatEx.nSamplesPerSec = 44100
WaveInFormatEx.wBitsPerSample = 8
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_4M16
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_4M16,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 1
WaveInFormatEx.nSamplesPerSec = 44100
WaveInFormatEx.wBitsPerSample = 16
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
Case IDM_4S16
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_4S16,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 2
WaveInFormatEx.nSamplesPerSec = 44100
WaveInFormatEx.wBitsPerSample = 16
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign * WaveInFormatEx.nSamplesPerSec
End Select
End Select
' イベントプロシージャの呼び出しを行います。
MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function
'-----------------------------------------------------------------------------
' ここから下は、イベントプロシージャを記述するための領域になります。
Sub MainWnd_Destroy()
Dim cnt As Long
If Record_Flag = TRUE Then
Stop_Flag = TRUE
waveInReset(hWaveIn)
ElseIf Play_Flag = TRUE Then
Stop_Flag = TRUE
waveOutReset(hWaveOut)
End If
Dim msg As MSG /*** 修正箇所 ***/
While 1
If PeekMessage(msg,0,0,0,PM_REMOVE) Then
TranslateMessage(msg)
DispatchMessage(msg)
If Play_Flag=FALSE And Record_Flag=FALSE Then Exit While
End If
Wend /*** ******** ***/
For cnt=0 To NumOfBuffers-1
free(WaveData[cnt])
Next
DestroyMenu(hMenu)
DestroyMenu(hMenuSub1)
wave_DestroyObjects()
PostQuitMessage(0)
End Sub
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
Dim cnt As Long
For cnt=0 To NumOfBuffers-1
WaveData[cnt] = malloc(BufferLength)
WaveHdr[cnt].lpData=WaveData[cnt]
FillMemory(WaveData[cnt],BufferLength,127)
Next
SetDlgItemText(hMainWnd,CommandButton1,"Record")
SetDlgItemText(hMainWnd,CommandButton2,"Play")
SetDlgItemText(hMainWnd,CommandButton3,"Stop")
SetMenu(hMainWnd,hMenu)
CheckMenuRadioItem(hMenu,IDM_1M08,IDM_4S16,IDM_1M08,MF_BYCOMMAND)
WaveInFormatEx.cbSize = SizeOf(WAVEFORMATEX)
WaveInFormatEx.wFormatTag = WAVE_FORMAT_PCM
WaveInFormatEx.nChannels = 1
WaveInFormatEx.nSamplesPerSec = 11025
WaveInFormatEx.wBitsPerSample = 8
WaveInFormatEx.nBlockAlign = WaveInFormatEx.nChannels*WaveInFormatEx.wBitsPerSample/8
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign*WaveInFormatEx.nSamplesPerSec
End Sub
Sub MainWnd_CommandButton1_Click()
/******WAVEファイルを作成******/
hMmio = mmioOpen("temp.wav",ByVal 0,MMIO_CREATE or MMIO_WRITE or MMIO_EXCLUSIVE)
/******WAVEチャンクを作成******/
MmioCkInfo.fccType = mmioStringToFOURCC("WAVE",0)
mmioCreateChunk(hMmio,MmioCkInfo,MMIO_CREATERIFF)
/******fmt チャンクを作成******/
MmioCkInfoSub.ckid = mmioStringToFOURCC("fmt ",0)
mmioCreateChunk(hMmio,MmioCkInfoSub,0)
/******fmt データを書き込み******/
mmioWrite(hMmio,VarPtr(WaveInFormatEx),SizeOf(PCMWAVEFORMAT))
mmioAscend(hMmio,MmioCkInfoSub,0)
/******WAVE入力デバイスを開く******/
waveInOpen(hWaveIn,WAVE_MAPPER,WaveInFormatEx,hMainWnd,0,CALLBACK_WINDOW)
Record_Flag = TRUE
End Sub
Sub MainWnd_CommandButton2_Click()
/******WAVEファイルを開く******/
hMmio = mmioOpen("temp.wav",MmioInfo,MMIO_READ)
/******WAVEチャンクにアクセス******/
MmioCkInfo.fccType = mmioStringToFOURCC("WAVE",0)
mmioDescend(hMmio,MmioCkInfo,ByVal 0,MMIO_FINDRIFF)
/******fmt データを読み込み******/
MmioCkInfoSub.ckid = mmioStringToFOURCC("fmt ",0)
mmioDescend(hMmio,MmioCkInfoSub,MmioCkInfo,MMIO_FINDCHUNK)
mmioRead(hMmio,VarPtr(WaveOutFormatEx),MmioCkInfoSub.cksize)
mmioAscend(hMmio,MmioCkInfoSub,0)
/******WAVE出力デバイスを開く******/
waveOutOpen(hWaveOut,WAVE_MAPPER,WaveOutFormatEx,hMainWnd,0,CALLBACK_WINDOW)
Play_Flag = TRUE
End Sub
Sub MainWnd_CommandButton3_Click()
Stop_Flag = TRUE
waveInReset(hWaveIn)
waveOutReset(hWaveOut)
Play_Flag = FALSE
Record_Flag = FALSE
End Sub
修正箇所はウィンドウのDESTROYイベント内にあります。
Re: [最重要]
さらに修正箇所が見つかりました。
といっても修正した同じ場所に間違いがありました。
Record_Flagについての条件分岐がなされていませんでしたが、
すでに編集で上のコードは修正してあります。
といっても修正した同じ場所に間違いがありました。
Record_Flagについての条件分岐がなされていませんでしたが、
すでに編集で上のコードは修正してあります。
返信@yu0627
久しぶりに、NoWestさんの録音コードを使ったソフトをActiveBasic v4.20.00でコンパイルしました。
そして、音質の高いモードで録音したら、録音ファイルがWindows Media Player 10(以下WMP10)で再生できません。
そこで、「WAVE録音と再生のサンプル」も再コンパイルしました。
しかし、低音質ではWMP10で再生できるのですが、高音質では再生することはできません。
バッファは5*1024、5KBにしてあります。
iTunesやQuickTimeでは再生できます。
また、ActiveBasicオフィシャルユーザーズガイドの第9章のSoundPlayerではしっかりと再生できます。
ただし、RealPlayerでは遅く再生されます。
僕の環境だけの現象かもしれませんが、どうなんでしょうか。
WMP10では、なぜかコーデックをダウンロードしようとします。その機能をはずすと、再生できません。
参考・・・録音ファイルのプロパティ
ビットレート:362kbps
オーディオサンプルサイズ:16bit
チャンネル:2(ステレオ)
オーディオサンプルレート:44KHz
オーディオ形式:PCM
そして、音質の高いモードで録音したら、録音ファイルがWindows Media Player 10(以下WMP10)で再生できません。
そこで、「WAVE録音と再生のサンプル」も再コンパイルしました。
しかし、低音質ではWMP10で再生できるのですが、高音質では再生することはできません。
バッファは5*1024、5KBにしてあります。
iTunesやQuickTimeでは再生できます。
また、ActiveBasicオフィシャルユーザーズガイドの第9章のSoundPlayerではしっかりと再生できます。
ただし、RealPlayerでは遅く再生されます。
僕の環境だけの現象かもしれませんが、どうなんでしょうか。
WMP10では、なぜかコーデックをダウンロードしようとします。その機能をはずすと、再生できません。
参考・・・録音ファイルのプロパティ
ビットレート:362kbps
オーディオサンプルサイズ:16bit
チャンネル:2(ステレオ)
オーディオサンプルレート:44KHz
オーディオ形式:PCM
Re: 返信@yu0627
> 参考・・・録音ファイルのプロパティ
> ビットレート:362kbps
> オーディオサンプルサイズ:16bit
> チャンネル:2(ステレオ)
> オーディオサンプルレート:44KHz
> オーディオ形式:PCM
一度ビットレートを320kbpsとか192kbpsに下げてみてはどうでしょう?
一般的な録音ソフトや変換ソフトでは確か320kbpsが最大ビットレートだったと思いまして・・・
一般的には、192kbps以上は人間の耳ではほとんど違いが分かりにくいみたいですけど、真相は不明です^^;
> ビットレート:362kbps
> オーディオサンプルサイズ:16bit
> チャンネル:2(ステレオ)
> オーディオサンプルレート:44KHz
> オーディオ形式:PCM
一度ビットレートを320kbpsとか192kbpsに下げてみてはどうでしょう?
一般的な録音ソフトや変換ソフトでは確か320kbpsが最大ビットレートだったと思いまして・・・
一般的には、192kbps以上は人間の耳ではほとんど違いが分かりにくいみたいですけど、真相は不明です^^;
返信@yu0627
一体どの周波数・ビット・チャンネルでどんなビットレートになるのか調べて見ました^^;
11025kHz 8bit モノラル・・・ 88kbps
11025kHz 8bit ステレオ・・・176kbps
11025kHz 16bit モノラル・・・176kbps
11025kHz 16bit ステレオ・・・352kbps
22050kHz 8bit モノラル・・・176kbps
22050kHz 8bit ステレオ・・・352kbps
22050kHz 16bit モノラル・・・352kbps
22050kHz 16bit ステレオ・・・181kbps(WMP10再生不可)
44100kHz 8bit モノラル・・・352kbps
44100kHz 8bit ステレオ・・・181kbps(WMP10再生不可)
44100kHz 16bit モノラル・・・181kbps(WMP10再生不可)
44100kHz 16bit ステレオ・・・362kbps(WMP10再生不可)
僕の環境では以上のようになりました。皆さんの環境ではどうなるか分かりませんが。
ビットレートの取得はエクスプローラのプロパティ→概要タブの部分にしています。
一度、X-CLEANERを使ったので、それが誤除去したのかと思いシステムの復元をしましたが変化なしです。
11025kHz 8bit モノラル・・・ 88kbps
11025kHz 8bit ステレオ・・・176kbps
11025kHz 16bit モノラル・・・176kbps
11025kHz 16bit ステレオ・・・352kbps
22050kHz 8bit モノラル・・・176kbps
22050kHz 8bit ステレオ・・・352kbps
22050kHz 16bit モノラル・・・352kbps
22050kHz 16bit ステレオ・・・181kbps(WMP10再生不可)
44100kHz 8bit モノラル・・・352kbps
44100kHz 8bit ステレオ・・・181kbps(WMP10再生不可)
44100kHz 16bit モノラル・・・181kbps(WMP10再生不可)
44100kHz 16bit ステレオ・・・362kbps(WMP10再生不可)
僕の環境では以上のようになりました。皆さんの環境ではどうなるか分かりませんが。
ビットレートの取得はエクスプローラのプロパティ→概要タブの部分にしています。
一度、X-CLEANERを使ったので、それが誤除去したのかと思いシステムの復元をしましたが変化なしです。
Re: 返信@yu0627
この件なのですが、うちのPCでも同じことが起こっています。> 一体どの周波数・ビット・チャンネルでどんなビットレートになるのか調べて見ました^^;
>
> 11025kHz 8bit モノラル・・・ 88kbps
> 11025kHz 8bit ステレオ・・・176kbps
> 11025kHz 16bit モノラル・・・176kbps
> 11025kHz 16bit ステレオ・・・352kbps
> 22050kHz 8bit モノラル・・・176kbps
> 22050kHz 8bit ステレオ・・・352kbps
> 22050kHz 16bit モノラル・・・352kbps
> 22050kHz 16bit ステレオ・・・181kbps(WMP10再生不可)
> 44100kHz 8bit モノラル・・・352kbps
> 44100kHz 8bit ステレオ・・・181kbps(WMP10再生不可)
> 44100kHz 16bit モノラル・・・181kbps(WMP10再生不可)
> 44100kHz 16bit ステレオ・・・362kbps(WMP10再生不可)
>
> 僕の環境では以上のようになりました。皆さんの環境ではどうなるか分かりませんが。
> ビットレートの取得はエクスプローラのプロパティ→概要タブの部分にしています。
> 一度、X-CLEANERを使ったので、それが誤除去したのかと思いシステムの復元をしましたが変化なしです。
しかしながら、私のプログラムはちゃんと規格を守っているので、”一般的なサウンドツール”では再生されないはずはありません。
おそらくですが、生のWAVEデータにWMPのデコーダが対応していないのではないでしょうか?
こちらではWindows付属のサウンドレコーダーでの再生は確認しています。
Re: 原因判明@NoWest
原因が分かりました。
WaveInFormatEx.nAvgBytesPerSecメンバの計算箇所で
DWordで計算されるべきところがWordで計算されていたのが原因です。
nBlockAlignメンバはWordなので計算した結果がWord値になっていたんですね。
道理でサンプリング周波数が小さいのが正常で大きいのがエラーになるわけです。
P.S.
バグを直したつもりだったんですが新たなバグを見付けてしまいました。
時間があれば、このサンプルは作り直してコード投稿の方にでも出します。
P.S.2
あっても無くても動くんですが、C++で構造体サイズを調べたところ
WAVEFORMATとPCMWAVEFORMAT、WAVEFORMATEXは
Type Align(1) ~~
End Type
のようにしないといけないようです。
WaveInFormatEx.nAvgBytesPerSecメンバの計算箇所で
DWordで計算されるべきところがWordで計算されていたのが原因です。
コード: 全て選択
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign As DWord * WaveInFormatEx.nSamplesPerSec
nBlockAlignメンバはWordなので計算した結果がWord値になっていたんですね。
道理でサンプリング周波数が小さいのが正常で大きいのがエラーになるわけです。
P.S.
バグを直したつもりだったんですが新たなバグを見付けてしまいました。
時間があれば、このサンプルは作り直してコード投稿の方にでも出します。
P.S.2
あっても無くても動くんですが、C++で構造体サイズを調べたところ
WAVEFORMATとPCMWAVEFORMAT、WAVEFORMATEXは
Type Align(1) ~~
End Type
のようにしないといけないようです。
返信@yu0627
> 原因が分かりました。
>
> WaveInFormatEx.nAvgBytesPerSecメンバの計算箇所で
> DWordで計算されるべきところがWordで計算されていたのが原因です。
>
>
>
>
> nBlockAlignメンバはWordなので計算した結果がWord値になっていたんですね。
> 道理でサンプリング周波数が小さいのが正常で大きいのがエラーになるわけです。
こちらでも改善確認いたしました。変換したファイルを見ると、
1411kbps 44100Hz 16bit ステレオ
と、なっており、しっかりとWMP10で再生できるようになりました。ありがとうございます。
> P.S.2
> あっても無くても動くんですが、C++で構造体サイズを調べたところ
> WAVEFORMATとPCMWAVEFORMAT、WAVEFORMATEXは
> Type Align(1) ~~
> End Type
> のようにしないといけないようです。
この点については、僕はまだ分かりません^^;
>
> WaveInFormatEx.nAvgBytesPerSecメンバの計算箇所で
> DWordで計算されるべきところがWordで計算されていたのが原因です。
>
>
コード: 全て選択
WaveInFormatEx.nAvgBytesPerSec = WaveInFormatEx.nBlockAlign As DWord * WaveInFormatEx.nSamplesPerSec
>
>
> nBlockAlignメンバはWordなので計算した結果がWord値になっていたんですね。
> 道理でサンプリング周波数が小さいのが正常で大きいのがエラーになるわけです。
こちらでも改善確認いたしました。変換したファイルを見ると、
1411kbps 44100Hz 16bit ステレオ
と、なっており、しっかりとWMP10で再生できるようになりました。ありがとうございます。
> P.S.2
> あっても無くても動くんですが、C++で構造体サイズを調べたところ
> WAVEFORMATとPCMWAVEFORMAT、WAVEFORMATEXは
> Type Align(1) ~~
> End Type
> のようにしないといけないようです。
この点については、僕はまだ分かりません^^;
またまた問題発生
またまた、このコードで問題が発生しました。
久しぶりに、AB4.24.00にて該当するコードを含んだプログラムをコンパイルし録音すると、
48バイト以上のデータが書き込まれません。サウンドのビットレートなどについては、OKです。
デバッグしてみたところ、ウインドウメッセージのコールバック関数内の、「WAVE入力デバイスのバッファが一杯になった時に呼ばれる」の
「dataデータを書き込み」の「mmioWrite(hMmio,pwh->lpData,pwh->dwBytesRecorded)」でなぜかアクセス違反がおきました。
なお、なぜかサンプルプログラムではうまくいって、それを組み込んだプログラムではうまくいきません。
やっぱり僕が作ったプログラムに問題があるのでしょうか。
参考までに、組み込みプログラム(MIDI Encorder)のソースを全部載せます。
久しぶりに、AB4.24.00にて該当するコードを含んだプログラムをコンパイルし録音すると、
48バイト以上のデータが書き込まれません。サウンドのビットレートなどについては、OKです。
デバッグしてみたところ、ウインドウメッセージのコールバック関数内の、「WAVE入力デバイスのバッファが一杯になった時に呼ばれる」の
「dataデータを書き込み」の「mmioWrite(hMmio,pwh->lpData,pwh->dwBytesRecorded)」でなぜかアクセス違反がおきました。
なお、なぜかサンプルプログラムではうまくいって、それを組み込んだプログラムではうまくいきません。
やっぱり僕が作ったプログラムに問題があるのでしょうか。
参考までに、組み込みプログラム(MIDI Encorder)のソースを全部載せます。
RecordAPI.sbp [ここをクリックすると内容が表示されます]
コード: 全て選択
'===========================================================
'
' Win32API 録音関係
'
'===========================================================
'定数宣言
Const NumOfBuffers = 5 'バッファ数
Const BufferLength = 100*1024 'バッファ長
'録音デバイス用変数宣言
Dim Play_Flag As DWord
Dim Record_Flag=FALSE As DWord
Dim Stop_Flag As DWord
Dim hWaveIn As HWAVEIN
Dim hWaveOut As HWAVEOUT
Dim WaveHdr[ELM(NumOfBuffers)] As WAVEHDR
Dim WaveOutFormatEx As WAVEFORMATEX
Dim WaveInFormatEx As WAVEFORMATEX
Dim hMmio As HMMIO
Dim MmioInfo As MMIOINFO
Dim MmioCkInfo As MMCKINFO
Dim MmioCkInfoSub As MMCKINFO
Dim WaveData[ELM(NumOfBuffers)] As *Byte
Dim WaveInCaps As WAVEINCAPS