//-------------------------------------------------------------------------------------------------- BOOL CSoundStream::Decompress(unsigned char *dest) { u32 dwSrcSize = dwSrcBufSize; BOOL r = true; VERIFY (hAcmStream); // check for EOF if (dwDecPos+dwSrcSize>dwTotalSize) { dwSrcSize=dwTotalSize-dwDecPos; r=false; } hf->r (WaveSource,dwSrcSize); stream.cbStruct=sizeof(stream); stream.fdwStatus=0; stream.pbSrc=WaveSource; stream.cbSrcLength=dwSrcSize; stream.pbDst=dest; stream.cbDstLength=dwDestBufSize; CHK_DX(acmStreamPrepareHeader(hAcmStream,&stream,0)); CHK_DX(acmStreamConvert(hAcmStream,&stream,0)); CHK_DX(acmStreamUnprepareHeader(hAcmStream,&stream,0)); dwDecPos+=stream.cbSrcLengthUsed; AppWriteDataToBuffer(writepos,WaveDest,stream.cbDstLengthUsed); return r; }
static DWORD wodWrite(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2) { PACMSTREAMHEADER ash; LPWAVEHDR lpWaveHdrDst; TRACE("(%p %p %08x)\n", wom, lpWaveHdrSrc, dwParam2); if (!wom->hAcmStream) { return waveOutWrite(wom->u.out.hInnerWave, lpWaveHdrSrc, dwParam2); } lpWaveHdrSrc->dwFlags |= WHDR_INQUEUE; ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved; /* acmStreamConvert will actually check that the new size is less than initial size */ ash->cbSrcLength = lpWaveHdrSrc->dwBufferLength; if (acmStreamConvert(wom->hAcmStream, ash, 0L) != MMSYSERR_NOERROR) { WARN("acmStreamConvert failed\n"); return MMSYSERR_ERROR; } lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER)); if (ash->cbSrcLength > ash->cbSrcLengthUsed) FIXME("Not all src buffer has been written, expect bogus sound\n"); else if (ash->cbSrcLength < ash->cbSrcLengthUsed) ERR("Codec has read more data than it is allowed to\n"); if (ash->cbDstLengthUsed == 0) { /* something went wrong in decoding */ FIXME("Got 0 length\n"); return MMSYSERR_ERROR; } lpWaveHdrDst->dwBufferLength = ash->cbDstLengthUsed; return waveOutWrite(wom->u.out.hInnerWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst)); }
void CACMStream::Convert(LPVOID src, DWORD size) { m_mmr = 0; if (m_hdr->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) { if (src != m_hdr->pbSrc || size > m_hdr->dwSrcUser) { Unprepare(); Prepare(src, size); } } else { Prepare(src, size); } m_mmr = acmStreamConvert(m_strm, m_hdr, ACM_STREAMCONVERTF_END| ACM_STREAMCONVERTF_START); if (m_mmr) raiseError(m_mmr, "Error during conversion"); }
void audio_resampler_acm::audio_receive(unsigned char *data, unsigned int size) { MMRESULT err; /* Checking for acm stream opened */ if (stream_opened) { /* Copy audio data from extern to internal source buffer */ memcpy(acm_header.pbSrc, data, size); acm_header.cbSrcLength = size; acm_header.cbDstLengthUsed = 0; err = acmStreamConvert(acm_stream, &acm_header, ACM_STREAMCONVERTF_BLOCKALIGN); if (err != MMSYSERR_NOERROR) { /* TODO: throw error */ MessageBox(0, _T("acmStreamConvert error"), _T("ERROR"), MB_ICONERROR); } /* Wait for sound conversion */ while ((ACMSTREAMHEADER_STATUSF_DONE & acm_header.fdwStatus) == 0); /* Copy resampled audio, to destination buffer */ //memcpy(pbOutputData, acm_header.pbDst, acm_header.cbDstLengthUsed); } }
int ToADPCM(short *Source, short *Dest, int Size) { int Src_size; int Dest_Size; Wave_Format.wFormatTag = WAVE_FORMAT_PCM; Wave_Format.nChannels = 1; Wave_Format.cbSize = 0; Wave_Format.wBitsPerSample = 16; Wave_Format.nSamplesPerSec = 44100; Wave_Format.nBlockAlign = Wave_Format.nChannels * Wave_Format.wBitsPerSample / 8; Wave_Format.nAvgBytesPerSec = Wave_Format.nSamplesPerSec * Wave_Format.nBlockAlign; ADPCM_Format.wfx.wFormatTag = WAVE_FORMAT_IMA_ADPCM; acmFormatSuggest(NULL, (LPWAVEFORMATEX) &Wave_Format, (LPWAVEFORMATEX) &ADPCM_Format, sizeof(TrueSpeech_Format), ACM_FORMATSUGGESTF_WFORMATTAG); acmStreamOpen(&Pack_Stream, NULL, (LPWAVEFORMATEX) &Wave_Format, (LPWAVEFORMATEX) &ADPCM_Format, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); Src_size = Size; unsigned long rawbufsize = 0; acmStreamSize(Pack_Stream, Src_size, &rawbufsize, ACM_STREAMSIZEF_SOURCE); Uint8 *Pack_Buf = (Uint8 *) malloc(Src_size + 8); memset(Pack_Buf, 0, Src_size + 8); Uint8 *rawbuf = (Uint8 *) malloc(rawbufsize + 8); memset(rawbuf, 0, rawbufsize + 8); ACMSTREAMHEADER Pack_Stream_Head; ZeroMemory(&Pack_Stream_Head, sizeof(ACMSTREAMHEADER)); Pack_Stream_Head.cbStruct = sizeof(ACMSTREAMHEADER); Pack_Stream_Head.pbSrc = (Uint8 *) Pack_Buf; Pack_Stream_Head.cbSrcLength = Src_size; Pack_Stream_Head.pbDst = rawbuf; Pack_Stream_Head.cbDstLength = rawbufsize; acmStreamPrepareHeader(Pack_Stream, &Pack_Stream_Head, 0); memcpy(Pack_Buf, Source, Src_size); acmStreamConvert(Pack_Stream, &Pack_Stream_Head, 0); Dest_Size = Pack_Stream_Head.cbDstLengthUsed; if(Dest_Size < Src_size) { memcpy(Dest, rawbuf, Dest_Size); } else { Dest_Size = 0; } acmStreamUnprepareHeader(Pack_Stream, &Pack_Stream_Head, 0); if(rawbuf) free(rawbuf); if(Pack_Buf) free(Pack_Buf); acmStreamClose(Pack_Stream, 0); return(Dest_Size); }
static GstFlowReturn acmmp3dec_chain (GstPad * pad, GstBuffer * buf) { MMRESULT res; ACMMP3Dec *dec = (ACMMP3Dec *) GST_PAD_PARENT (pad); guchar *data = GST_BUFFER_DATA (buf); gint len = GST_BUFFER_SIZE (buf); GstFlowReturn ret = GST_FLOW_OK; if (len > ACM_BUFFER_SIZE) { GST_WARNING_OBJECT (dec, "Impossibly large mp3 frame!"); ret = GST_FLOW_ERROR; goto done; } if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE && (dec->timestamp == GST_CLOCK_TIME_NONE || GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) { dec->timestamp = GST_BUFFER_TIMESTAMP (buf); } memcpy (dec->header.pbSrc, data, len); dec->header.cbSrcLength = len; /* Now we have a buffer ready to go */ res = acmStreamConvert (dec->stream, &dec->header, ACM_STREAMCONVERTF_BLOCKALIGN); if (res) { GST_WARNING_OBJECT (dec, "Failed to decode data"); ret = GST_FLOW_OK; /* Maybe it was just a corrupt frame */ goto done; } if (dec->header.cbSrcLengthUsed > 0) { if (dec->header.cbSrcLengthUsed != dec->header.cbSrcLength) { GST_WARNING_OBJECT (dec, "ACM decoder didn't consume all data!"); /* We could handle this, but it shouldn't be possible, so don't try * for now */ ret = GST_FLOW_ERROR; goto done; } /* Write out any data produced */ acmmp3dec_push_output (dec); } done: gst_buffer_unref (buf); return ret; }
static void CALLBACK widCallback(HWAVEIN hWave, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { WAVEMAPDATA* wim = (WAVEMAPDATA*)dwInstance; TRACE("(%p %u %lx %lx %lx);\n", hWave, uMsg, dwInstance, dwParam1, dwParam2); if (!WAVEMAP_IsData(wim)) { ERR("Bad data\n"); return; } if (uMsg != WIM_OPEN && hWave != wim->u.in.hInnerWave) ERR("Shouldn't happen (%p %p)\n", hWave, wim->u.in.hInnerWave); switch (uMsg) { case WIM_OPEN: case WIM_CLOSE: /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */ break; case WIM_DATA: if (wim->hAcmStream) { LPWAVEHDR lpWaveHdrSrc = (LPWAVEHDR)dwParam1; PACMSTREAMHEADER ash = (PACMSTREAMHEADER)((LPSTR)lpWaveHdrSrc - sizeof(ACMSTREAMHEADER)); LPWAVEHDR lpWaveHdrDst = (LPWAVEHDR)ash->dwUser; /* convert data just gotten from waveIn into requested format */ if (acmStreamConvert(wim->hAcmStream, ash, 0L) != MMSYSERR_NOERROR) { ERR("ACM conversion failed\n"); return; } else { TRACE("Converted %d bytes into %d\n", ash->cbSrcLengthUsed, ash->cbDstLengthUsed); } /* and setup the wavehdr to return accordingly */ lpWaveHdrDst->dwFlags &= ~WHDR_INQUEUE; lpWaveHdrDst->dwFlags |= WHDR_DONE; lpWaveHdrDst->dwBytesRecorded = ash->cbDstLengthUsed; dwParam1 = (DWORD_PTR)lpWaveHdrDst; } break; default: ERR("Unknown msg %u\n", uMsg); } DriverCallback(wim->dwCallback, HIWORD(wim->dwFlags), (HDRVR)wim->u.in.hOuterWave, uMsg, wim->dwClientInstance, dwParam1, dwParam2); }
void audioFeed(char *buf, int len) { int work = len; int chunk; if(!work) return; char *bufPtr = buf; for(;;) { if(lastDecodedSize != -1) { chunk = lastDecodedSize-audioDecodedCursor; if(chunk > work) chunk = work; memcpy(bufPtr,audioDecoded + audioDecodedCursor * sampleSize,chunk*sampleSize); bufPtr += chunk*sampleSize; work -= chunk; audioDecodedCursor += chunk; } if(!work) break; //if we are at the end of our audiostream, we can't read any more! if(encodeCursor == audioSampleCount) { //write silence memset(bufPtr,0,work*sampleSize); bAudioPaused = true; return; } audioReadChunk(); acmStreamConvert(acmStream,&audioStreamHeader,0); lastDecodedSize = audioStreamHeader.cbDstLengthUsed / sampleSize; audioDecodedCursor = 0; } }
static GstFlowReturn acmmp3dec_finish_stream (ACMMP3Dec * dec) { MMRESULT res; GstFlowReturn ret = GST_FLOW_OK; dec->header.cbSrcLength = 0; /* Flush out any remaining data internal to the decoder */ res = acmStreamConvert (dec->stream, &dec->header, ACM_STREAMCONVERTF_BLOCKALIGN | ACM_STREAMCONVERTF_END); if (res) { GST_WARNING_OBJECT (dec, "Failed to decode data"); return ret; } ret = acmmp3dec_push_output (dec); return ret; }
LRESULT CAcm::Convert(LPVOID lpDestBuf){ // ここでDirectSoundのLockしたメモリポインタを渡す if (!m_bOpen) { return 1; // Openできてへんのに呼ぶなっちゅーに! } m_acmheader.cbStruct = sizeof(m_acmheader); m_acmheader.pbSrc = (BYTE*)m_lpSrcBuf; m_acmheader.cbSrcLength = m_dwSrcLength; m_acmheader.pbDst = (BYTE*)lpDestBuf; // ここにコピーしたいねん! m_acmheader.cbDstLength = m_dwDestLength; if (acmStreamPrepareHeader(m_hAcm,&m_acmheader,NULL)!=0) { return 2; // 勘弁して〜(笑) } if (acmStreamConvert(m_hAcm,&m_acmheader,NULL)!=0){ return 3; // ダメじゃん(笑) } return 0; // 任務終了 }
void acm_cv_convert (const converter_fmt_t *cfmt, u_char *state, sample *src_buf, int src_len, sample *dst_buf, int dst_len) { ACMSTREAMHEADER ash; LPHACMSTREAM lphs; UNUSED(cfmt); memset(&ash, 0, sizeof(ash)); ash.cbStruct = sizeof(ash); ash.pbSrc = (LPBYTE)src_buf; ash.cbSrcLength = src_len * sizeof(sample); ash.pbDst = (LPBYTE)dst_buf; ash.cbDstLength = dst_len * sizeof(sample); lphs = (LPHACMSTREAM)state; if (acmStreamPrepareHeader(*lphs, &ash, 0) || acmStreamConvert(*lphs, &ash, ACM_STREAMCONVERTF_BLOCKALIGN)) { memset(dst_buf, 0, dst_len * sizeof(sample)); } return; }
/// <summary> /// <c>wACMStreamConvert</c> /// </summary> /// <remarks> /// </remarks> /// <param name="has"></param> /// <param name="pash"></param> /// <param name="fdwConvert"></param> /// <returns>HRESULT __stdcall</returns> HRESULT __stdcall wACMStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash, ULONG fdwConvert) { PSTR pszErrorMessage; MMRESULT hResult; InternalFunctionSpew("GameOS_DirectSound", "acmStreamConvert(0x%x, 0x%x, 0x%x)", has, pash, fdwConvert); hResult = acmStreamConvert(has, pash, fdwConvert); if (MMFAILED(hResult)) { pszErrorMessage = ErrorNumberToMessage(hResult); //PAUSE( if ( InternalFunctionPause( "FAILED (0x%x - %s) - acmStreamConvert(0x%x, 0x%x, 0x%x)", hResult, pszErrorMessage, has, pash, fdwConvert) ) ENTER_DEBUGGER; } return hResult; }
static int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen) { ACMSTREAMHEADER ash; HRESULT hr; DWORD srcsize=0; DWORD len=minlen; acm_context_t *priv = sh_audio->context; acmStreamSize(priv->handle, len, &srcsize, ACM_STREAMSIZEF_DESTINATION); mp_msg(MSGT_WIN32,MSGL_DBG3,"acm says: srcsize=%ld (buffsize=%d) out_size=%ld\n",srcsize,sh_audio->a_in_buffer_size,len); if(srcsize<sh_audio->wf->nBlockAlign){ srcsize=sh_audio->wf->nBlockAlign; acmStreamSize(priv->handle, srcsize, &len, ACM_STREAMSIZEF_SOURCE); if(len>maxlen) len=maxlen; } // if(srcsize==0) srcsize=((WAVEFORMATEX *)&sh_audio->o_wf_ext)->nBlockAlign; if(srcsize>sh_audio->a_in_buffer_size) srcsize=sh_audio->a_in_buffer_size; // !!!!!! if(sh_audio->a_in_buffer_len<srcsize){ sh_audio->a_in_buffer_len+= demux_read_data(sh_audio->ds,&sh_audio->a_in_buffer[sh_audio->a_in_buffer_len], srcsize-sh_audio->a_in_buffer_len); } mp_msg(MSGT_WIN32,MSGL_DBG3,"acm convert %d -> %ld bytes\n",sh_audio->a_in_buffer_len,len); memset(&ash, 0, sizeof(ash)); ash.cbStruct=sizeof(ash); ash.fdwStatus=0; ash.dwUser=0; ash.pbSrc=sh_audio->a_in_buffer; ash.cbSrcLength=sh_audio->a_in_buffer_len; ash.pbDst=buf; ash.cbDstLength=len; hr=acmStreamPrepareHeader(priv->handle,&ash,0); if(hr){ mp_msg(MSGT_WIN32,MSGL_V,"ACM_Decoder: acmStreamPrepareHeader error %d\n",(int)hr); return -1; } hr=acmStreamConvert(priv->handle,&ash,0); if(hr){ mp_msg(MSGT_WIN32,MSGL_DBG2,"ACM_Decoder: acmStreamConvert error %d\n",(int)hr); switch(hr) { case ACMERR_NOTPOSSIBLE: case ACMERR_UNPREPARED: mp_msg(MSGT_WIN32, MSGL_DBG2, "ACM_Decoder: acmStreamConvert error: probarly not initialized!\n"); } // return -1; } mp_msg(MSGT_WIN32,MSGL_DBG2,"acm converted %ld -> %ld\n",ash.cbSrcLengthUsed,ash.cbDstLengthUsed); if(ash.cbSrcLengthUsed>=sh_audio->a_in_buffer_len){ sh_audio->a_in_buffer_len=0; } else { sh_audio->a_in_buffer_len-=ash.cbSrcLengthUsed; memcpy(sh_audio->a_in_buffer,&sh_audio->a_in_buffer[ash.cbSrcLengthUsed],sh_audio->a_in_buffer_len); } len=ash.cbDstLengthUsed; hr=acmStreamUnprepareHeader(priv->handle,&ash,0); if(hr){ mp_msg(MSGT_WIN32,MSGL_V,"ACM_Decoder: acmStreamUnprepareHeader error %d\n",(int)hr); } return len; }
void ConvertNode(HWND hwnd, AFile* node, const char* fname, WORD tag) { FSHandle* file; HANDLE wavfile; RIFFHeader riffhdr; ChunkHeader chunkhdr; DWORD riffsize,factsize,datasize,written,rate,buffpos,pcmsize,dstsize,sizeToFill,sizeFilled; DWORD pos_riffsize,pos_factsize,pos_datasize; WORD channels,bits; char str[MAX_PATH+100],*pcmBuffer=NULL,*dstBuffer=NULL; LPWAVEFORMATEX pwfex; ACMFORMATTAGDETAILS aftd={0}; MMRESULT mmr; WAVEFORMATEX wfexPCM; HACMSTREAM hACMStream; ACMSTREAMHEADER acmshdr; if ((file=FSOpenForPlayback(hwnd,node,&rate,&channels,&bits))==NULL) return; wfexPCM.wFormatTag=WAVE_FORMAT_PCM; wfexPCM.nChannels=channels; wfexPCM.nSamplesPerSec=rate; wfexPCM.wBitsPerSample=bits; wfexPCM.cbSize=0; wfexPCM.nBlockAlign=channels*(bits/8); wfexPCM.nAvgBytesPerSec=rate*wfexPCM.nBlockAlign; switch (tag) { case WAVE_FORMAT_PCM: pwfex=NULL; // ??? hACMStream=NULL; dstBuffer=NULL; // ??? pcmBuffer=(char*)GlobalAlloc(GPTR,BUFFERSIZE); break; default: aftd.cbStruct=sizeof(aftd); aftd.dwFormatTag=tag; mmr=acmFormatTagDetails(NULL,&aftd,ACM_FORMATTAGDETAILSF_LARGESTSIZE); if (mmr!=MMSYSERR_NOERROR) { AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"Failed to get details for wave format tag: 0x%X",tag); ReportMMError(hwnd,mmr,str); return; } pwfex=(LPWAVEFORMATEX)LocalAlloc(LPTR,aftd.cbFormatSize); pwfex->wFormatTag=tag; mmr=acmFormatSuggest(NULL,&wfexPCM,pwfex,aftd.cbFormatSize,ACM_FORMATSUGGESTF_WFORMATTAG); if (mmr!=MMSYSERR_NOERROR) { LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"No format suggested for wave format tag: 0x%X",tag); ReportMMError(hwnd,mmr,str); return; } mmr=acmStreamOpen(&hACMStream,NULL,&wfexPCM,pwfex,NULL,0,0,ACM_STREAMOPENF_NONREALTIME); if (mmr!=MMSYSERR_NOERROR) { LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"Failed to open conversion stream for wave format tag: 0x%X",tag); ReportMMError(hwnd,mmr,str); return; } if (acmStreamSize(hACMStream,BUFFERSIZE,&dstsize,ACM_STREAMSIZEF_SOURCE)!=MMSYSERR_NOERROR) dstsize=BUFFERSIZE; pcmBuffer=(char*)GlobalAlloc(GPTR,BUFFERSIZE); dstBuffer=(char*)GlobalAlloc(GPTR,dstsize); memset(&acmshdr,0x00,sizeof(acmshdr)); // ??? acmshdr.cbStruct=sizeof(ACMSTREAMHEADER); acmshdr.fdwStatus=0; acmshdr.pbSrc=pcmBuffer; acmshdr.cbSrcLength=BUFFERSIZE; acmshdr.cbSrcLengthUsed=0; acmshdr.pbDst=dstBuffer; acmshdr.cbDstLength=dstsize; acmshdr.cbDstLengthUsed=0; mmr=acmStreamPrepareHeader(hACMStream,&acmshdr,0L); if (mmr!=MMSYSERR_NOERROR) { GlobalFree(dstBuffer); GlobalFree(pcmBuffer); acmStreamClose(hACMStream,0); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); ReportMMError(hwnd,mmr,"Failed to prepare conversion stream header."); return; } acmshdr.cbSrcLength=0; } if (!EnsureDirPresence(fname)) { if (hACMStream!=NULL) { acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); } GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); return; } wavfile=CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (wavfile==INVALID_HANDLE_VALUE) { if (hACMStream!=NULL) { acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); } GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); wsprintf(str,"Cannot open WAV file: %s",fname); ReportError(hwnd,str,NULL); return; } ShowProgressHeaderMsg(fname); datasize=0; factsize=0; ShowProgressStateMsg("Writing RIFF header..."); SetFilePointer(wavfile,0,NULL,FILE_BEGIN); lstrcpy(riffhdr.riffid,IDSTR_RIFF); lstrcpy(riffhdr.rifftype,IDSTR_WAVE); riffhdr.riffsize=0; WriteFile(wavfile,&riffhdr,sizeof(RIFFHeader),&written,NULL); pos_riffsize=SetFilePointer(wavfile,0,NULL,FILE_CURRENT)-sizeof(riffhdr.rifftype)-sizeof(riffhdr.riffsize); CorrectOddPos(wavfile); ShowProgressStateMsg("Writing fmt chunk..."); lstrcpy(chunkhdr.id,IDSTR_fmt); switch (tag) { case WAVE_FORMAT_PCM: chunkhdr.size=sizeof(wfexPCM); WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); WriteFile(wavfile,&wfexPCM,chunkhdr.size,&written,NULL); CorrectOddPos(wavfile); break; default: chunkhdr.size=aftd.cbFormatSize; WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); WriteFile(wavfile,pwfex,chunkhdr.size,&written,NULL); CorrectOddPos(wavfile); lstrcpy(chunkhdr.id,IDSTR_fact); chunkhdr.size=sizeof(factsize); WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); pos_factsize=SetFilePointer(wavfile,0,NULL,FILE_CURRENT); WriteFile(wavfile,&factsize,sizeof(factsize),&written,NULL); CorrectOddPos(wavfile); } lstrcpy(chunkhdr.id,IDSTR_data); chunkhdr.size=datasize; WriteFile(wavfile,&chunkhdr,sizeof(chunkhdr),&written,NULL); pos_datasize=SetFilePointer(wavfile,0,NULL,FILE_CURRENT)-sizeof(datasize); while (1) { if (IsCancelled()) break; switch (tag) { case WAVE_FORMAT_PCM: sizeToFill=BUFFERSIZE; sizeFilled=0; break; default: if (acmshdr.cbSrcLengthUsed!=0L) { memmove(pcmBuffer,pcmBuffer+acmshdr.cbSrcLengthUsed,acmshdr.cbSrcLength-acmshdr.cbSrcLengthUsed); acmshdr.cbSrcLength-=acmshdr.cbSrcLengthUsed; } if (acmshdr.cbSrcLength<BUFFERSIZE) sizeToFill=BUFFERSIZE-acmshdr.cbSrcLength; sizeFilled=acmshdr.cbSrcLength; } wsprintf(str,"Converting %s data block to PCM...",file->node->afID); ShowProgressStateMsg(str); pcmsize=0; if (sizeToFill>0) pcmsize=AFPLUGIN(node)->FillPCMBuffer(file,pcmBuffer+sizeFilled,sizeToFill,&buffpos); if (tag==WAVE_FORMAT_PCM) { if (pcmsize==0L) break; ShowProgressStateMsg("Writing WAV data block..."); WriteFile(wavfile,pcmBuffer,pcmsize,&written,NULL); if (written!=pcmsize) { ReportError(hwnd,"Failure writing WAV file.",NULL); SetCancelFlag(); break; } datasize+=written; } else { acmshdr.cbSrcLength+=pcmsize; if (acmshdr.cbSrcLength==0L) break; acmshdr.fdwStatus^=ACMSTREAMHEADER_STATUSF_DONE; acmshdr.cbSrcLengthUsed=0; acmshdr.cbDstLength=dstsize; acmshdr.cbDstLengthUsed=0; wsprintf(str,"Compressing PCM data block..."); ShowProgressStateMsg(str); mmr=acmStreamConvert(hACMStream,&acmshdr,ACM_STREAMCONVERTF_BLOCKALIGN); if (mmr!=MMSYSERR_NOERROR) { CloseHandle(wavfile); DeleteFile(fname); acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); ReportMMError(hwnd,mmr,"Error during compression."); return; } if (acmshdr.cbSrcLengthUsed==0L) { acmshdr.fdwStatus^=ACMSTREAMHEADER_STATUSF_DONE; acmStreamConvert(hACMStream,&acmshdr,0L); } factsize+=acmshdr.cbSrcLengthUsed/wfexPCM.nBlockAlign; ShowProgressStateMsg("Writing WAV data block..."); WriteFile(wavfile,dstBuffer,acmshdr.cbDstLengthUsed,&written,NULL); if (written!=acmshdr.cbDstLengthUsed) { ReportError(hwnd,"Failure writing WAV file.",NULL); SetCancelFlag(); break; } datasize+=written; } ShowProgress(FSGetFilePointer(file),FSGetFileSize(file)); // ??? } if (IsCancelled()) { ShowProgressStateMsg("Deleting WAV file..."); CloseHandle(wavfile); DeleteFile(fname); } else { CorrectOddPos(wavfile); ShowProgressStateMsg("Rewriting WAV header..."); riffsize=GetFileSize(wavfile,NULL)-8; SetFilePointer(wavfile,pos_riffsize,NULL,FILE_BEGIN); WriteFile(wavfile,&riffsize,sizeof(riffsize),&written,NULL); if (tag!=WAVE_FORMAT_PCM) { SetFilePointer(wavfile,pos_factsize,NULL,FILE_BEGIN); WriteFile(wavfile,&factsize,sizeof(factsize),&written,NULL); } SetFilePointer(wavfile,pos_datasize,NULL,FILE_BEGIN); WriteFile(wavfile,&datasize,sizeof(datasize),&written,NULL); CloseHandle(wavfile); } if (hACMStream!=NULL) { ShowProgressStateMsg("Closing conversion stream..."); acmStreamUnprepareHeader(hACMStream,&acmshdr,0L); acmStreamClose(hACMStream,0); } ShowProgressStateMsg("Freeing conversion buffers..."); GlobalFree(dstBuffer); GlobalFree(pcmBuffer); LocalFree(pwfex); wsprintf(str,"Shutting down %s decoder...",file->node->afID); ShowProgressStateMsg(str); AFPLUGIN(node)->ShutdownPlayback(file); FSCloseFile(file); }
int ToMP3(short *Source, short *Dest, int Size, int BitRate) { int Src_size; int Dest_Size; Wave_Format.wFormatTag = WAVE_FORMAT_PCM; Wave_Format.nChannels = 1; Wave_Format.cbSize = 0; Wave_Format.wBitsPerSample = 16; Wave_Format.nSamplesPerSec = 44100; Wave_Format.nBlockAlign = Wave_Format.nChannels * Wave_Format.wBitsPerSample / 8; Wave_Format.nAvgBytesPerSec = Wave_Format.nSamplesPerSec * Wave_Format.nBlockAlign; MP3_Format.wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3; MP3_Format.wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES; MP3_Format.wfx.nChannels = 1; MP3_Format.wfx.nSamplesPerSec = 44100; MP3_Format.wfx.nAvgBytesPerSec = BitRate * (1000 / 8); MP3_Format.wfx.wBitsPerSample = 0; MP3_Format.wfx.nBlockAlign = 1; MP3_Format.wID = MPEGLAYER3_ID_MPEG; MP3_Format.fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF; MP3_Format.nBlockSize = 0; MP3_Format.nFramesPerBlock = 0; MP3_Format.nCodecDelay = 0; acmStreamOpen(&Pack_Stream, NULL, (LPWAVEFORMATEX) &Wave_Format, (LPWAVEFORMATEX) &MP3_Format, NULL, 0, 0, 0); Src_size = Size; unsigned long rawbufsize = 0; acmStreamSize(Pack_Stream, Src_size, &rawbufsize, ACM_STREAMSIZEF_SOURCE); rawbufsize += MP3_FRAMES_LAG * 2; Uint8 *Pack_Buf = (Uint8 *) malloc(Src_size + (MP3_FRAMES_LAG * 4) + 8); memset(Pack_Buf, 0, Src_size + (MP3_FRAMES_LAG * 4) + 8); Uint8 *rawbuf = (Uint8 *) malloc(rawbufsize + (MP3_FRAMES_LAG * 4) + 8); memset(rawbuf, 0, rawbufsize + (MP3_FRAMES_LAG * 4) + 8); ACMSTREAMHEADER Pack_Stream_Head; ZeroMemory(&Pack_Stream_Head, sizeof(ACMSTREAMHEADER)); Pack_Stream_Head.cbStruct = sizeof(ACMSTREAMHEADER); Pack_Stream_Head.pbSrc = (Uint8 *) Pack_Buf; Pack_Stream_Head.cbSrcLength = Src_size + (MP3_FRAMES_LAG * 2); Pack_Stream_Head.pbDst = rawbuf; Pack_Stream_Head.cbDstLength = rawbufsize; acmStreamPrepareHeader(Pack_Stream, &Pack_Stream_Head, 0); memcpy(Pack_Buf, Source, Src_size); acmStreamConvert(Pack_Stream, &Pack_Stream_Head, 0); Dest_Size = Pack_Stream_Head.cbDstLengthUsed; if(Dest_Size < Src_size) { memcpy(Dest, rawbuf, Dest_Size); } else { Dest_Size = 0; } acmStreamUnprepareHeader(Pack_Stream, &Pack_Stream_Head, 0); acmStreamClose(Pack_Stream, 0); if(rawbuf) free(rawbuf); if(Pack_Buf) free(Pack_Buf); return(Dest_Size); }
ConvertOutput AudioConverterStream::Convert(const BYTE* inBuffer, int inSize) { if (isProxy) { // Source and destination formats are identical, so just pass the input through to the output ConvertOutput rv = { const_cast<BYTE*>(inBuffer), inSize }; return rv; } outSize = 0; int prevSrcLength = header.cbSrcLength; int usedInSize = 0; while (inSize + startOffset) { int curInSize = std::min(inSize, static_cast<int>(sizeof(inWorkBuffer) - startOffset)); memcpy(inWorkBuffer + startOffset, inBuffer + usedInSize, curInSize); usedInSize += curInSize; inSize -= curInSize; header.cbSrcLength = curInSize + startOffset; MMRESULT mm = acmStreamConvert(stream, &header, ACM_STREAMCONVERTF_BLOCKALIGN); if (mm != MMSYSERR_NOERROR) { m_failed = true; break; } // Append to output int prevOutSize = outSize; outSize += header.cbDstLengthUsed; ReserveOutBuffer(outSize); memcpy(outBuffer + prevOutSize, outWorkBuffer, header.cbDstLengthUsed); // Recycle unused input startOffset = header.cbSrcLength - header.cbSrcLengthUsed; // startOffset = number of leftover bytes if (startOffset > 0 && header.cbSrcLengthUsed) { memmove(inWorkBuffer, inWorkBuffer + header.cbSrcLengthUsed, startOffset); } if (header.cbDstLengthUsed == 0 && header.cbSrcLengthUsed == 0) { break; } } header.cbSrcLength = prevSrcLength; if (header.cbDstLengthUsed == 0 && header.cbSrcLengthUsed == 0 && startOffset == sizeof(inWorkBuffer)) { m_failed = true; } if (subConverter) { return subConverter->Convert(outBuffer, outSize); } ConvertOutput rv = { outBuffer, outSize }; return rv; }
static HRESULT WINAPI ACMWrapper_Receive(TransformFilter *tf, IMediaSample *pSample) { ACMWrapperImpl* This = (ACMWrapperImpl*)tf; AM_MEDIA_TYPE amt; IMediaSample* pOutSample = NULL; DWORD cbDstStream, cbSrcStream; LPBYTE pbDstStream; LPBYTE pbSrcStream = NULL; ACMSTREAMHEADER ash; BOOL unprepare_header = FALSE, preroll; MMRESULT res; HRESULT hr; LONGLONG tStart = -1, tStop = -1, tMed; EnterCriticalSection(&This->tf.filter.csFilter); hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); LeaveCriticalSection(&This->tf.filter.csFilter); return hr; } preroll = (IMediaSample_IsPreroll(pSample) == S_OK); IMediaSample_GetTime(pSample, &tStart, &tStop); cbSrcStream = IMediaSample_GetActualDataLength(pSample); /* Prevent discontinuities when codecs 'absorb' data but not give anything back in return */ if (IMediaSample_IsDiscontinuity(pSample) == S_OK) { This->lasttime_real = tStart; This->lasttime_sent = tStart; } else if (This->lasttime_real == tStart) tStart = This->lasttime_sent; else WARN("Discontinuity\n"); tMed = tStart; TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); LeaveCriticalSection(&This->tf.filter.csFilter); return hr; } ash.pbSrc = pbSrcStream; ash.cbSrcLength = cbSrcStream; while(hr == S_OK && ash.cbSrcLength) { hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); LeaveCriticalSection(&This->tf.filter.csFilter); return hr; } IMediaSample_SetPreroll(pOutSample, preroll); hr = IMediaSample_SetActualDataLength(pOutSample, 0); assert(hr == S_OK); hr = IMediaSample_GetPointer(pOutSample, &pbDstStream); if (FAILED(hr)) { ERR("Unable to get pointer to buffer (%x)\n", hr); goto error; } cbDstStream = IMediaSample_GetSize(pOutSample); ash.cbStruct = sizeof(ash); ash.fdwStatus = 0; ash.dwUser = 0; ash.pbDst = pbDstStream; ash.cbDstLength = cbDstStream; if ((res = acmStreamPrepareHeader(This->has, &ash, 0))) { ERR("Cannot prepare header %d\n", res); goto error; } unprepare_header = TRUE; if (IMediaSample_IsDiscontinuity(pSample) == S_OK) { res = acmStreamConvert(This->has, &ash, ACM_STREAMCONVERTF_START); IMediaSample_SetDiscontinuity(pOutSample, TRUE); /* One sample could be converted to multiple packets */ IMediaSample_SetDiscontinuity(pSample, FALSE); } else { res = acmStreamConvert(This->has, &ash, 0); IMediaSample_SetDiscontinuity(pOutSample, FALSE); } if (res) { if(res != MMSYSERR_MOREDATA) ERR("Cannot convert data header %d\n", res); goto error; } TRACE("used in %u/%u, used out %u/%u\n", ash.cbSrcLengthUsed, ash.cbSrcLength, ash.cbDstLengthUsed, ash.cbDstLength); hr = IMediaSample_SetActualDataLength(pOutSample, ash.cbDstLengthUsed); assert(hr == S_OK); /* Bug in acm codecs? It apparantly uses the input, but doesn't necessarily output immediately kl*/ if (!ash.cbSrcLengthUsed) { WARN("Sample was skipped? Outputted: %u\n", ash.cbDstLengthUsed); ash.cbSrcLength = 0; goto error; } TRACE("Sample start time: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000)); if (ash.cbSrcLengthUsed == cbSrcStream) { IMediaSample_SetTime(pOutSample, &tStart, &tStop); tStart = tMed = tStop; } else if (tStop != tStart) { tMed = tStop - tStart; tMed = tStart + tMed * ash.cbSrcLengthUsed / cbSrcStream; IMediaSample_SetTime(pOutSample, &tStart, &tMed); tStart = tMed; } else { ERR("No valid timestamp found\n"); IMediaSample_SetTime(pOutSample, NULL, NULL); } TRACE("Sample stop time: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000)); LeaveCriticalSection(&This->tf.filter.csFilter); hr = BaseOutputPinImpl_Deliver((BaseOutputPin*)This->tf.ppPins[1], pOutSample); EnterCriticalSection(&This->tf.filter.csFilter); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { if (FAILED(hr)) ERR("Error sending sample (%x)\n", hr); goto error; } error: if (unprepare_header && (res = acmStreamUnprepareHeader(This->has, &ash, 0))) ERR("Cannot unprepare header %d\n", res); unprepare_header = FALSE; ash.pbSrc += ash.cbSrcLengthUsed; ash.cbSrcLength -= ash.cbSrcLengthUsed; if (pOutSample) IMediaSample_Release(pOutSample); pOutSample = NULL; } This->lasttime_real = tStop; This->lasttime_sent = tMed; LeaveCriticalSection(&This->tf.filter.csFilter); return hr; }
int ToAT3(short *Source, short *Dest, int Size, int BitRate) { int Src_size; int Dest_Size; int i; Wave_Format.wFormatTag = WAVE_FORMAT_PCM; Wave_Format.nChannels = 2; Wave_Format.cbSize = 0; Wave_Format.wBitsPerSample = 16; Wave_Format.nSamplesPerSec = 44100; Wave_Format.nBlockAlign = Wave_Format.nChannels * Wave_Format.wBitsPerSample / 8; Wave_Format.nAvgBytesPerSec = Wave_Format.nSamplesPerSec * Wave_Format.nBlockAlign; At3_Format.wfx.wFormatTag = 0x270; At3_Format.wfx.nChannels = 2; At3_Format.wfx.nSamplesPerSec = 44100; At3_Format.wfx.nAvgBytesPerSec = BitRate * 125; switch(BitRate) { case 66: At3_Format.wfx.nBlockAlign = 192; break; case 105: At3_Format.wfx.nBlockAlign = 304; break; case 132: At3_Format.wfx.nBlockAlign = 384; break; } At3_Format.wfx.wBitsPerSample = 0; At3_Format.wfx.cbSize = 0xe; At3_Format.wRevision = 1; At3_Format.nSamplesPerBlock = 0x800; At3_Format.abReserved[2] = 1; At3_Format.abReserved[4] = 1; At3_Format.abReserved[6] = 1; acmStreamOpen(&Pack_Stream, NULL, (LPWAVEFORMATEX) &Wave_Format, (LPWAVEFORMATEX) &At3_Format, NULL, 0, 0, 0); short *dwSource = (short *) malloc(Size * 2 + 8); memset(dwSource, 0, Size * 2 + 8); for(i = 0; i < Size / 2; i++) { dwSource[(i * 2)] = Source[i]; dwSource[(i * 2) + 1] = 0; } Source = dwSource; Size *= 2; Src_size = Size; unsigned long rawbufsize = 0; acmStreamSize(Pack_Stream, Src_size, &rawbufsize, ACM_STREAMSIZEF_SOURCE); Uint8 *Pack_Buf = (Uint8 *) malloc(Src_size + 8); memset(Pack_Buf, 0, Src_size + 8); Uint8 *rawbuf = (Uint8 *) malloc(rawbufsize + 8); memset(rawbuf, 0, rawbufsize + 8); ACMSTREAMHEADER Pack_Stream_Head; ZeroMemory(&Pack_Stream_Head, sizeof(ACMSTREAMHEADER)); Pack_Stream_Head.cbStruct = sizeof(ACMSTREAMHEADER); Pack_Stream_Head.pbSrc = (Uint8 *) Pack_Buf; Pack_Stream_Head.cbSrcLength = Src_size; Pack_Stream_Head.pbDst = rawbuf; Pack_Stream_Head.cbDstLength = rawbufsize; acmStreamPrepareHeader(Pack_Stream, &Pack_Stream_Head, 0); memcpy(Pack_Buf, Source, Src_size); acmStreamConvert(Pack_Stream, &Pack_Stream_Head, 0); Dest_Size = Pack_Stream_Head.cbDstLengthUsed; if(Dest_Size < Src_size) { memcpy(Dest, rawbuf, Dest_Size); } else { Dest_Size = 0; } acmStreamUnprepareHeader(Pack_Stream, &Pack_Stream_Head, 0); if(rawbuf) free(rawbuf); if(Pack_Buf) free(Pack_Buf); if(dwSource) free(dwSource); acmStreamClose(Pack_Stream, 0); return(Dest_Size); }
static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start, LONG samples, LPVOID buffer, LONG buffersize, DWORD flags, LPLONG sampwritten, LPLONG byteswritten) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; HRESULT hr; ULONG size; TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples, buffer, buffersize, flags, sampwritten, byteswritten); /* clear return parameters if given */ if (sampwritten != NULL) *sampwritten = 0; if (byteswritten != NULL) *byteswritten = 0; /* check parameters */ if (buffer == NULL && (buffersize > 0 || samples > 0)) return AVIERR_BADPARAM; /* Have we write capability? */ if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0) return AVIERR_READONLY; /* also need a compressor */ if (This->has == NULL) return AVIERR_NOCOMPRESSOR; /* map our sizes to pStream sizes */ size = buffersize; CONVERT_THIS_to_STREAM(&size); CONVERT_THIS_to_STREAM(&start); /* no bytes to write? -- short circuit */ if (size == 0) { return IAVIStream_Write(This->pStream, -1, samples, buffer, size, flags, sampwritten, byteswritten); } /* Need to free source buffer used for reading? */ if (This->acmStreamHdr.pbSrc != NULL) { HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc); This->acmStreamHdr.pbSrc = NULL; This->acmStreamHdr.dwSrcUser = 0; } /* Need bigger destination buffer? */ if (This->acmStreamHdr.pbDst == NULL || This->acmStreamHdr.dwDstUser < size) { if (This->acmStreamHdr.pbDst == NULL) This->acmStreamHdr.pbDst = HeapAlloc(GetProcessHeap(), 0, size); else This->acmStreamHdr.pbDst = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbDst, size); if (This->acmStreamHdr.pbDst == NULL) return AVIERR_MEMORY; This->acmStreamHdr.dwDstUser = size; } This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr); This->acmStreamHdr.cbSrcLengthUsed = 0; This->acmStreamHdr.cbDstLengthUsed = 0; This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser; /* need to prepare stream? */ This->acmStreamHdr.pbSrc = buffer; This->acmStreamHdr.cbSrcLength = buffersize; if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) { if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) { This->acmStreamHdr.pbSrc = NULL; This->acmStreamHdr.cbSrcLength = 0; return AVIERR_COMPRESSOR; } } /* now do the conversion */ /* FIXME: use ACM_CONVERTF_* flags */ if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK) hr = AVIERR_COMPRESSOR; else hr = AVIERR_OK; This->acmStreamHdr.pbSrc = NULL; This->acmStreamHdr.cbSrcLength = 0; if (FAILED(hr)) return hr; return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst, This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten, byteswritten); }
static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size) { ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter; AM_MEDIA_TYPE amt; HRESULT hr; IMediaSample* pSample = NULL; DWORD cbDstStream; LPBYTE pbDstStream; ACMSTREAMHEADER ash; DWORD offset = 0; BOOL stop = FALSE; BOOL unprepare_header = FALSE; MMRESULT res; TRACE("(%p)->(%p,%ld)\n", This, data, size); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); goto error; } while(!stop) { DWORD rem_buf = This->max_size - This->current_size; DWORD rem_smp = size - offset; DWORD copy_size = min(rem_buf, rem_smp); memcpy(This->buffer + This->current_size, data + offset, copy_size); This->current_size += copy_size; offset += copy_size; if (offset == size) stop = TRUE; if (This->current_size < This->max_size) break; hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%lx)\n", hr); goto error; } hr = IMediaSample_SetActualDataLength(pSample, 0); assert(hr == S_OK); hr = IMediaSample_GetPointer(pSample, &pbDstStream); if (FAILED(hr)) { ERR("Unable to get pointer to buffer (%lx)\n", hr); goto error; } cbDstStream = IMediaSample_GetSize(pSample); ash.cbStruct = sizeof(ash); ash.fdwStatus = 0; ash.dwUser = 0; ash.pbSrc = This->buffer; ash.cbSrcLength = This->current_size; ash.pbDst = pbDstStream; ash.cbDstLength = cbDstStream; if ((res = acmStreamPrepareHeader(This->has, &ash, 0))) { ERR("Cannot prepare header %d\n", res); goto error; } unprepare_header = TRUE; if ((res = acmStreamConvert(This->has, &ash, This->reinit_codec ? ACM_STREAMCONVERTF_START : 0))) { ERR("Cannot convert data header %d\n", res); goto error; } This->reinit_codec = FALSE; TRACE("used in %lu, used out %lu\n", ash.cbSrcLengthUsed, ash.cbDstLengthUsed); hr = IMediaSample_SetActualDataLength(pSample, ash.cbDstLengthUsed); assert(hr == S_OK); if (ash.cbSrcLengthUsed < ash.cbSrcLength) { This->current_size = ash.cbSrcLength - ash.cbSrcLengthUsed; memmove(This->buffer, This->buffer + ash.cbSrcLengthUsed, This->current_size); } else This->current_size = 0; hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pSample); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { ERR("Error sending sample (%lx)\n", hr); goto error; } error: if (unprepare_header && (res = acmStreamUnprepareHeader(This->has, &ash, 0))) ERR("Cannot unprepare header %d\n", res); if (pSample) IMediaSample_Release(pSample); } return hr; }
BOOL ClSoundDS::AddSoundBuffer(int handle,char *fileBuf,BOOL b3DSound) { HRESULT hr; RiffHead riffHead; FmtHead fmtHead; PCMWAVEFORMAT pcmFormat; LPBYTE lpBlockAdd1, lpBlockAdd2; DWORD blockSize1, blockSize2; CopyMemory(&riffHead,fileBuf,sizeof(RiffHead)); fileBuf += sizeof(RiffHead); if(strncmp(riffHead.riff,"RIFF",4) || strncmp(riffHead.type,"WAVE",4)){ return FALSE; } if(NULL==lpDSBufferTop){ lpDSBufferTop = lpDSBufferTail = new ClSoundBuffer; }else{ lpDSBufferTail->lpNext = new ClSoundBuffer; lpDSBufferTail->lpNext->lpPrev = lpDSBufferTail; lpDSBufferTail = lpDSBufferTail->lpNext; } lpDSBufferTail->bufType = memory_sound; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); CopyMemory(&pcmFormat,fileBuf,sizeof(PCMWAVEFORMAT)); if(pcmFormat.wf.wFormatTag == WAVE_FORMAT_PCM){ fileBuf += fmtHead.size; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); while(0!=strncmp(fmtHead.fmt,"data",4)){ fileBuf += fmtHead.size; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); } DSBUFFERDESC dsbdesc; WAVEFORMATEX audioFmt; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; if(b3DSound) dsbdesc.dwFlags |= (DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE); dsbdesc.dwBufferBytes = fmtHead.size; CopyMemory(&audioFmt,&pcmFormat,sizeof(WAVEFORMAT)); audioFmt.wBitsPerSample = pcmFormat.wBitsPerSample; audioFmt.cbSize = 0; dsbdesc.lpwfxFormat = &audioFmt; hr = lpDSound->CreateSoundBuffer(&dsbdesc, &lpTmpBuffer, NULL); lpTmpBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID *)&lpDSBufferTail->lpDSBuffer); RELEASE(lpTmpBuffer); hr = lpDSBufferTail->lpDSBuffer->Lock(0,fmtHead.size, (LPVOID*)&lpBlockAdd1, &blockSize1,(LPVOID*)&lpBlockAdd2, &blockSize2, 0); if(DS_OK==hr){ CopyMemory(lpBlockAdd1,fileBuf,blockSize1); if(fmtHead.size>blockSize1){ CopyMemory(lpBlockAdd2,fileBuf+blockSize1,blockSize2); } lpDSBufferTail->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); } lpDSBufferTail->handle = handle; }else{ WAVEFORMATEX dstWF; WAVEFORMATEX *pwfxInfo; WORD cbExtraAlloc; MMRESULT mmResult; fileBuf += sizeof(PCMWAVEFORMAT); CopyMemory(&cbExtraAlloc,fileBuf,sizeof(WORD)); fileBuf += sizeof(WORD); pwfxInfo = (WAVEFORMATEX *)cl_malloc(sizeof(WAVEFORMATEX) +cbExtraAlloc); CopyMemory(pwfxInfo,&pcmFormat,sizeof(PCMWAVEFORMAT)); pwfxInfo->cbSize = cbExtraAlloc; CopyMemory((char *)pwfxInfo +sizeof(WAVEFORMATEX),fileBuf,cbExtraAlloc); fileBuf += (fmtHead.size -sizeof(WAVEFORMATEX)); CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); while(0!=strncmp(fmtHead.fmt,"data",4)){ fileBuf += fmtHead.size; CopyMemory(&fmtHead,fileBuf,sizeof(FmtHead)); fileBuf += sizeof(FmtHead); } ZeroMemory(&dstWF,sizeof(dstWF)); dstWF.wFormatTag = WAVE_FORMAT_PCM; mmResult = acmFormatSuggest( NULL, pwfxInfo, &dstWF, sizeof(dstWF), ACM_FORMATSUGGESTF_WFORMATTAG); if(mmResult != 0){ myOutputDebugString("オーディオ圧縮が無効です\n"); return FALSE; } HACMSTREAM hAcm = NULL; ACMSTREAMHEADER ash; AcmBuffer acmDst; AcmBuffer acmSrc; acmStreamOpen(&hAcm, NULL,pwfxInfo,&dstWF, NULL, 0L, 0L, ACM_STREAMOPENF_NONREALTIME); acmSrc.dwStreamSize = fmtHead.size; acmStreamSize(hAcm, acmSrc.dwStreamSize, &acmDst.dwStreamSize, ACM_STREAMSIZEF_SOURCE); cl_free(pwfxInfo); acmSrc.lpStream = (LPBYTE)cl_malloc(acmSrc.dwStreamSize); acmDst.lpStream = (LPBYTE)cl_malloc(acmDst.dwStreamSize); ZeroMemory(&ash,sizeof(ash)); ash.cbStruct = sizeof(ash); ash.pbSrc = acmSrc.lpStream; ash.cbSrcLength = acmSrc.dwStreamSize; ash.dwSrcUser = acmSrc.dwStreamSize; ash.pbDst = acmDst.lpStream; ash.cbDstLength = acmDst.dwStreamSize; ash.dwDstUser = acmDst.dwStreamSize; acmStreamPrepareHeader(hAcm,&ash,0); CopyMemory(acmSrc.lpStream,fileBuf,acmSrc.dwStreamSize); MMRESULT nError = acmStreamConvert(hAcm,&ash, ACM_STREAMCONVERTF_BLOCKALIGN); DSBUFFERDESC dsbdesc; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS; if(b3DSound) dsbdesc.dwFlags |= (DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE); dsbdesc.dwBufferBytes = ash.cbDstLengthUsed; dsbdesc.lpwfxFormat = &dstWF; hr = lpDSound->CreateSoundBuffer(&dsbdesc, &lpTmpBuffer, NULL); lpTmpBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID *)&lpDSBufferTail->lpDSBuffer); RELEASE(lpTmpBuffer); hr = lpDSBufferTail->lpDSBuffer->Lock(0,ash.cbDstLengthUsed, (LPVOID*)&lpBlockAdd1, &blockSize1,(LPVOID*)&lpBlockAdd2, &blockSize2, 0); if(DS_OK==hr){ if(ash.cbDstLengthUsed < blockSize1){ CopyMemory(lpBlockAdd1, acmDst.lpStream, ash.cbDstLengthUsed); ZeroMemory(lpBlockAdd1 +ash.cbDstLengthUsed, blockSize1 -ash.cbDstLengthUsed); if(blockSize2)ZeroMemory(lpBlockAdd2,blockSize2); }else{ CopyMemory(lpBlockAdd1, acmDst.lpStream, blockSize1); if(blockSize2){ CopyMemory(lpBlockAdd2, acmDst.lpStream+blockSize1, ash.cbDstLengthUsed -blockSize1); } } lpDSBufferTail->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); } if(hAcm){ acmStreamUnprepareHeader(hAcm,&ash,0); acmStreamClose(hAcm,0); cl_free(acmSrc.lpStream); cl_free(acmDst.lpStream); } lpDSBufferTail->handle = handle; } return TRUE; } // ClSoundDS::AddSoundBuffer
static void test_prepareheader(void) { HACMSTREAM has; ADPCMWAVEFORMAT *src; WAVEFORMATEX dst; MMRESULT mr; ACMSTREAMHEADER hdr; BYTE buf[sizeof(WAVEFORMATEX) + 32], pcm[2048], input[512]; ADPCMCOEFSET *coef; src = (ADPCMWAVEFORMAT*)buf; coef = src->aCoef; src->wfx.cbSize = 32; src->wfx.wFormatTag = WAVE_FORMAT_ADPCM; src->wfx.nSamplesPerSec = 22050; src->wfx.wBitsPerSample = 4; src->wfx.nChannels = 1; src->wfx.nBlockAlign = 512; src->wfx.nAvgBytesPerSec = 11025; src->wSamplesPerBlock = 0x3f4; src->wNumCoef = 7; coef[0].iCoef1 = 0x0100; coef[0].iCoef2 = 0x0000; coef[1].iCoef1 = 0x0200; coef[1].iCoef2 = 0xff00; coef[2].iCoef1 = 0x0000; coef[2].iCoef2 = 0x0000; coef[3].iCoef1 = 0x00c0; coef[3].iCoef2 = 0x0040; coef[4].iCoef1 = 0x00f0; coef[4].iCoef2 = 0x0000; coef[5].iCoef1 = 0x01cc; coef[5].iCoef2 = 0xff30; coef[6].iCoef1 = 0x0188; coef[6].iCoef2 = 0xff18; dst.cbSize = 0; dst.wFormatTag = WAVE_FORMAT_PCM; dst.nSamplesPerSec = 22050; dst.wBitsPerSample = 8; dst.nChannels = 1; dst.nBlockAlign = dst.wBitsPerSample * dst.nChannels / 8; dst.nAvgBytesPerSec = dst.nSamplesPerSec * dst.nBlockAlign; mr = acmStreamOpen(&has, NULL, (WAVEFORMATEX*)src, &dst, NULL, 0, 0, 0); ok(mr == MMSYSERR_NOERROR, "open failed: 0x%x\n", mr); memset(input, 0, sizeof(input)); memset(&hdr, 0, sizeof(hdr)); hdr.cbStruct = sizeof(hdr); hdr.pbSrc = input; hdr.cbSrcLength = sizeof(input); hdr.pbDst = pcm; hdr.cbDstLength = sizeof(pcm); mr = acmStreamPrepareHeader(has, &hdr, 0); ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "header wasn't prepared: 0x%x\n", hdr.fdwStatus); mr = acmStreamUnprepareHeader(has, &hdr, 0); ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == 0, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); memset(&hdr, 0, sizeof(hdr)); hdr.cbStruct = sizeof(hdr); hdr.pbSrc = input; hdr.cbSrcLength = sizeof(input); hdr.pbDst = pcm; hdr.cbDstLength = sizeof(pcm); hdr.fdwStatus = ACMSTREAMHEADER_STATUSF_DONE; mr = acmStreamPrepareHeader(has, &hdr, 0); ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == (ACMSTREAMHEADER_STATUSF_PREPARED | ACMSTREAMHEADER_STATUSF_DONE), "header wasn't prepared: 0x%x\n", hdr.fdwStatus); hdr.cbSrcLengthUsed = 12345; hdr.cbDstLengthUsed = 12345; hdr.fdwStatus &= ~ACMSTREAMHEADER_STATUSF_DONE; mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); ok(mr == MMSYSERR_NOERROR, "convert failed: 0x%x\n", mr); ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "conversion was not done: 0x%x\n", hdr.fdwStatus); ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "expected %d, got %d\n", hdr.cbSrcLength, hdr.cbSrcLengthUsed); todo_wine ok(hdr.cbDstLengthUsed == 1010, "expected 1010, got %d\n", hdr.cbDstLengthUsed); mr = acmStreamUnprepareHeader(has, &hdr, 0); ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); /* The 2 next tests are related to Lost Horizon (bug 24723) */ memset(&hdr, 0, sizeof(hdr)); hdr.cbStruct = sizeof(hdr); hdr.pbSrc = input; hdr.cbSrcLength = sizeof(input); hdr.pbDst = pcm; hdr.cbDstLength = -4; mr = acmStreamPrepareHeader(has, &hdr, 0); if (sizeof(void *) == 4) /* 64 bit fails on this test */ { ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "header wasn't prepared: 0x%x\n", hdr.fdwStatus); hdr.cbSrcLengthUsed = 12345; hdr.cbDstLengthUsed = 12345; hdr.fdwStatus &= ~ACMSTREAMHEADER_STATUSF_DONE; mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); ok(mr == MMSYSERR_NOERROR, "convert failed: 0x%x\n", mr); ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "conversion was not done: 0x%x\n", hdr.fdwStatus); ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "expected %d, got %d\n", hdr.cbSrcLength, hdr.cbSrcLengthUsed); todo_wine ok(hdr.cbDstLengthUsed == 1010, "expected 1010, got %d\n", hdr.cbDstLengthUsed); mr = acmStreamUnprepareHeader(has, &hdr, 0); ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); } else ok(mr == MMSYSERR_INVALPARAM, "expected 11, got %d\n", mr); memset(&hdr, 0, sizeof(hdr)); hdr.cbStruct = sizeof(hdr); hdr.pbSrc = input; hdr.cbSrcLength = 24; hdr.pbDst = pcm; hdr.cbDstLength = -4; mr = acmStreamPrepareHeader(has, &hdr, 0); todo_wine { ok(mr == ACMERR_NOTPOSSIBLE, "expected 0x200, got 0x%x\n", mr); ok(hdr.fdwStatus == 0, "expected 0, got 0x%x\n", hdr.fdwStatus); hdr.cbSrcLengthUsed = 12345; hdr.cbDstLengthUsed = 12345; mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); ok(mr == ACMERR_UNPREPARED, "expected 0x202, got 0x%x\n", mr); ok(hdr.cbSrcLengthUsed == 12345, "expected 12345, got %d\n", hdr.cbSrcLengthUsed); ok(hdr.cbDstLengthUsed == 12345, "expected 12345, got %d\n", hdr.cbDstLengthUsed); mr = acmStreamUnprepareHeader(has, &hdr, 0); ok(mr == ACMERR_UNPREPARED, "expected 0x202, got 0x%x\n", mr); } /* Less output space than required */ memset(&hdr, 0, sizeof(hdr)); hdr.cbStruct = sizeof(hdr); hdr.pbSrc = input; hdr.cbSrcLength = sizeof(input); hdr.pbDst = pcm; hdr.cbDstLength = 32; mr = acmStreamPrepareHeader(has, &hdr, 0); ok(mr == MMSYSERR_NOERROR, "prepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_PREPARED, "header wasn't prepared: 0x%x\n", hdr.fdwStatus); hdr.cbSrcLengthUsed = 12345; hdr.cbDstLengthUsed = 12345; hdr.fdwStatus &= ~ACMSTREAMHEADER_STATUSF_DONE; mr = acmStreamConvert(has, &hdr, ACM_STREAMCONVERTF_BLOCKALIGN); ok(mr == MMSYSERR_NOERROR, "convert failed: 0x%x\n", mr); ok(hdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE, "conversion was not done: 0x%x\n", hdr.fdwStatus); todo_wine ok(hdr.cbSrcLengthUsed == hdr.cbSrcLength, "expected %d, got %d\n", hdr.cbSrcLength, hdr.cbSrcLengthUsed); todo_wine ok(hdr.cbDstLengthUsed == hdr.cbDstLength, "expected %d, got %d\n", hdr.cbDstLength, hdr.cbDstLengthUsed); mr = acmStreamUnprepareHeader(has, &hdr, 0); ok(mr == MMSYSERR_NOERROR, "unprepare failed: 0x%x\n", mr); ok(hdr.fdwStatus == ACMSTREAMHEADER_STATUSF_DONE, "header wasn't unprepared: 0x%x\n", hdr.fdwStatus); mr = acmStreamClose(has, 0); ok(mr == MMSYSERR_NOERROR, "close failed: 0x%x\n", mr); }
// // FillBuffer // // Stuffs the buffer with data HRESULT CSynthStream::FillBuffer(IMediaSample *pms) { CheckPointer(pms,E_POINTER); BYTE *pData; HRESULT hr = pms->GetPointer(&pData); if (FAILED(hr)) { return hr; } // This function must hold the state lock because it calls // FillPCMAudioBuffer(). CAutoLock lStateLock(m_pParent->pStateLock()); // This lock must be held because this function uses // m_dwTempPCMBufferSize, m_hPCMToMSADPCMConversionStream, // m_rtSampleTime, m_fFirstSampleDelivered and // m_llSampleMediaTimeStart. CAutoLock lShared(&m_cSharedState); WAVEFORMATEX* pwfexCurrent = (WAVEFORMATEX*)m_mt.Format(); if (WAVE_FORMAT_PCM == pwfexCurrent->wFormatTag) { m_Synth->FillPCMAudioBuffer(*pwfexCurrent, pData, pms->GetSize()); hr = pms->SetActualDataLength(pms->GetSize()); if (FAILED(hr)) return hr; } else { // This filter only supports two audio formats: PCM and ADPCM. ASSERT(WAVE_FORMAT_ADPCM == pwfexCurrent->wFormatTag); // Create PCM audio samples and then compress them. We use the // Audio Compression Manager (ACM) API to convert the samples to // the ADPCM format. ACMSTREAMHEADER ACMStreamHeader; ACMStreamHeader.cbStruct = sizeof(ACMStreamHeader); ACMStreamHeader.fdwStatus = 0; ACMStreamHeader.dwUser = 0; ACMStreamHeader.cbSrcLength = m_dwTempPCMBufferSize; ACMStreamHeader.cbSrcLengthUsed = 0; ACMStreamHeader.dwSrcUser = 0; ACMStreamHeader.pbDst = pData; ACMStreamHeader.cbDstLength = pms->GetSize(); ACMStreamHeader.cbDstLengthUsed = 0; ACMStreamHeader.dwDstUser = 0; ACMStreamHeader.pbSrc = new BYTE[m_dwTempPCMBufferSize]; if (NULL == ACMStreamHeader.pbSrc) { return E_OUTOFMEMORY; } WAVEFORMATEX wfexPCMAudio; DerivePCMFormatFromADPCMFormatStructure(*pwfexCurrent, &wfexPCMAudio); m_Synth->FillPCMAudioBuffer(wfexPCMAudio, ACMStreamHeader.pbSrc, ACMStreamHeader.cbSrcLength); MMRESULT mmr = acmStreamPrepareHeader(m_hPCMToMSADPCMConversionStream, &ACMStreamHeader, 0); // acmStreamPrepareHeader() returns 0 if no errors occur. if (mmr != 0) { delete [] ACMStreamHeader.pbSrc; return E_FAIL; } mmr = acmStreamConvert(m_hPCMToMSADPCMConversionStream, &ACMStreamHeader, ACM_STREAMCONVERTF_BLOCKALIGN); MMRESULT mmrUnprepare = acmStreamUnprepareHeader(m_hPCMToMSADPCMConversionStream, &ACMStreamHeader, 0); delete [] ACMStreamHeader.pbSrc; // acmStreamConvert() andacmStreamUnprepareHeader() returns 0 if no errors occur. if ((mmr != 0) || (mmrUnprepare != 0)) { return E_FAIL; } hr = pms->SetActualDataLength(ACMStreamHeader.cbDstLengthUsed); if (FAILED(hr)) { return hr; } } // Set the sample's time stamps. CRefTime rtStart = m_rtSampleTime; m_rtSampleTime = rtStart + (REFERENCE_TIME)(UNITS * pms->GetActualDataLength()) / (REFERENCE_TIME)pwfexCurrent->nAvgBytesPerSec; hr = pms->SetTime((REFERENCE_TIME*)&rtStart, (REFERENCE_TIME*)&m_rtSampleTime); if (FAILED(hr)) { return hr; } // Set the sample's properties. hr = pms->SetPreroll(FALSE); if (FAILED(hr)) { return hr; } hr = pms->SetMediaType(NULL); if (FAILED(hr)) { return hr; } hr = pms->SetDiscontinuity(!m_fFirstSampleDelivered); if (FAILED(hr)) { return hr; } hr = pms->SetSyncPoint(!m_fFirstSampleDelivered); if (FAILED(hr)) { return hr; } LONGLONG llMediaTimeStart = m_llSampleMediaTimeStart; DWORD dwNumAudioSamplesInPacket = (pms->GetActualDataLength() * BITS_PER_BYTE) / (pwfexCurrent->nChannels * pwfexCurrent->wBitsPerSample); LONGLONG llMediaTimeStop = m_llSampleMediaTimeStart + dwNumAudioSamplesInPacket; hr = pms->SetMediaTime(&llMediaTimeStart, &llMediaTimeStop); if (FAILED(hr)) { return hr; } m_llSampleMediaTimeStart = llMediaTimeStop; m_fFirstSampleDelivered = TRUE; return NOERROR; }
ClResult ClSoundDS::play(int handle,int repeat) { ClSoundBuffer *lpSoundBuffer; HRESULT hr; lpSoundBuffer = SelectSoundBuffer(handle); if(NULL==lpSoundBuffer)return Cl_PCM_NOTFOUND; lpSoundBuffer->endPt = -1; if(PCM_STOP!=lpSoundBuffer->status) Stop(handle); lpSoundBuffer->repeat = repeat; lpSoundBuffer->nextMusicNum = -1; if(memory_sound==lpSoundBuffer->bufType){ switch(repeat){ case (1): lpSoundBuffer->lpDSBuffer->Play(0,0,0); break; case (0): lpSoundBuffer->lpDSBuffer->Play(0,0,DSBPLAY_LOOPING); break; default: { DWORD dwThreadID; DSBPOSITIONNOTIFY pn; lpSoundBuffer->lpDSBuffer->QueryInterface(IID_IDirectSoundNotify8, (LPVOID*)&lpSoundBuffer->lpDSNotify); lpSoundBuffer->hEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL); pn.dwOffset = DSBPN_OFFSETSTOP; pn.hEventNotify = lpSoundBuffer->hEvent[0]; lpSoundBuffer->lpDSNotify->SetNotificationPositions(1,&pn); lpSoundBuffer->hLoopThread = CreateThread(NULL,0,SoundLoop,lpSoundBuffer,0,&dwThreadID); lpSoundBuffer->lpDSBuffer->Play(0,0,0); } break; } }else{ lpReadFile->StreamSeekFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpSoundBuffer->dataTopOffset,FILE_BEGIN); char *lpBlockAdd1, *lpBlockAdd2; DWORD blockSize1, blockSize2; hr = lpSoundBuffer->lpDSBuffer->Lock(0,lpSoundBuffer->streamBlockSize, (LPVOID*)&lpBlockAdd1, &blockSize1,(LPVOID*)&lpBlockAdd2, &blockSize2, 0); if(DS_OK==hr){ if(WAVE_FORMAT_OGG==lpSoundBuffer->wFormatTag){ char workBuf[4096]; char outBuf[0x20000]; int rsize,outsize,ret; rsize = lpReadFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,workBuf,4096); ret = lpSoundBuffer->o_dat->DecodeOGG(workBuf,rsize,outBuf,0x20000,&outsize); int remainSize = blockSize1; int writeSize = 0; while(remainSize>=outsize && remainSize>0){ CopyMemory(lpBlockAdd1+writeSize,outBuf,outsize); remainSize -= outsize; writeSize += outsize; if(ret==OGG_DEC_END && lpSoundBuffer->nextStream>=0){ int size; lpSoundBuffer->readFile->StreamCloseFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum); lpSoundBuffer->streamNum = lpSoundBuffer->readFile->StreamOpenFileNum(lpSoundBuffer->arcFileNum,lpSoundBuffer->nextStream,size); lpSoundBuffer->musicNum = lpSoundBuffer->nextStream; lpSoundBuffer->nextStream = -1; ret = OGG_DEC_CONTINUE; } if(ret!=OGG_DEC_CONTINUE){ ZeroMemory(lpBlockAdd1+writeSize,remainSize); remainSize = 0; break; } if(remainSize > 0){ rsize = lpReadFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,workBuf,4096); ret = lpSoundBuffer->o_dat->DecodeOGG(workBuf,rsize,outBuf,0x20000,&outsize); } } if(remainSize){ CopyMemory(lpBlockAdd1+writeSize,outBuf,remainSize); lpSoundBuffer->leakSize = outsize -remainSize; lpSoundBuffer->leakBuff = new BYTE[lpSoundBuffer->leakSize]; CopyMemory(lpSoundBuffer->leakBuff,outBuf +remainSize,lpSoundBuffer->leakSize); } }else if(NULL==lpSoundBuffer->hAcm){ lpReadFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpBlockAdd1,blockSize1); if(lpSoundBuffer->streamBlockSize>blockSize1){ lpReadFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpBlockAdd2,blockSize2); } }else{ lpReadFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,(char *)lpSoundBuffer->acmSrc.lpStream,lpSoundBuffer->acmSrc.dwStreamSize); MMRESULT nError = acmStreamConvert(lpSoundBuffer->hAcm,&lpSoundBuffer->ash, ACM_STREAMCONVERTF_BLOCKALIGN); if(0==nError){ int remainSize = blockSize1; int writeSize = 0; while(remainSize>=lpSoundBuffer->ash.cbDstLengthUsed && remainSize>0){ CopyMemory(lpBlockAdd1+writeSize,lpSoundBuffer->acmDst.lpStream,lpSoundBuffer->ash.cbDstLengthUsed); remainSize -= lpSoundBuffer->ash.cbDstLengthUsed; writeSize += lpSoundBuffer->ash.cbDstLengthUsed; if(remainSize > 0){ lpReadFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,(char *)lpSoundBuffer->acmSrc.lpStream,lpSoundBuffer->acmSrc.dwStreamSize); nError = acmStreamConvert(lpSoundBuffer->hAcm,&lpSoundBuffer->ash, ACM_STREAMCONVERTF_BLOCKALIGN); } } if(remainSize){ CopyMemory(lpBlockAdd1+writeSize,lpSoundBuffer->acmDst.lpStream,remainSize); lpSoundBuffer->leakSize = lpSoundBuffer->ash.cbDstLengthUsed -remainSize; lpSoundBuffer->leakBuff = new BYTE[lpSoundBuffer->leakSize]; CopyMemory(lpSoundBuffer->leakBuff,lpSoundBuffer->acmDst.lpStream +remainSize,lpSoundBuffer->leakSize); } } } lpSoundBuffer->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); } DWORD dwThreadID; DSBPOSITIONNOTIFY pn[3]; lpSoundBuffer->lpDSBuffer->QueryInterface(IID_IDirectSoundNotify8, (LPVOID*)&lpSoundBuffer->lpDSNotify); lpSoundBuffer->hEvent[0] = CreateEvent(NULL, FALSE, FALSE, NULL); lpSoundBuffer->hEvent[1] = CreateEvent(NULL, FALSE, FALSE, NULL); lpSoundBuffer->hEvent[2] = CreateEvent(NULL, FALSE, FALSE, NULL); pn[0].dwOffset = DWORD(lpSoundBuffer->streamBlockSize*0.1f); pn[0].hEventNotify = lpSoundBuffer->hEvent[0]; pn[1].dwOffset = DWORD(lpSoundBuffer->streamBlockSize*1.1f); pn[1].hEventNotify = lpSoundBuffer->hEvent[1]; pn[2].dwOffset = DSBPN_OFFSETSTOP; pn[2].hEventNotify = lpSoundBuffer->hEvent[2]; lpSoundBuffer->lpDSNotify->SetNotificationPositions(3,pn); lpSoundBuffer->hLoopThread = CreateThread(NULL,0,StreamLoop,lpSoundBuffer,0,&dwThreadID); lpSoundBuffer->lpDSBuffer->Play(0,0,DSBPLAY_LOOPING); } lpSoundBuffer->status = PCM_PLAY; return Cl_OK; } // ClSoundDS::play
DWORD CPlayer::WavPlayerThread() { BOOL fFlush = FALSE; if (m_pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) { // PCM DWORD cbInBuf, cbRead; while (TRUE) { // 停止フラグのチェック if (m_fStop) return RET_STOP; if (!m_pOutHdr) m_pOutHdr = m_Output.GetBuffer(); { // Critical Sectionのセット CAutoLock lock(&m_csecThread); if (m_fSeek) { if (m_Status == MAP_STATUS_PLAY) m_fPlay = TRUE; m_Reverb.Reset(); m_Echo.Reset(); m_BassBoost.Reset(); m_3DChorus.Reset(); m_Output.Reset(); m_fSeek = FALSE; m_pOutHdr = NULL; continue; } // 読み込み cbRead = min(m_dwDataSize - m_dwCurrentSize, m_cbOutBuf); if (!m_Reader.Read((LPBYTE)m_pOutHdr->lpData, cbRead, &cbInBuf) || !cbInBuf) { if (GetLastError() != ERROR_SUCCESS) return RET_ERROR; fFlush = TRUE; } Preamp((LPBYTE)m_pOutHdr->lpData, cbInBuf); m_dwCurrentSize += cbInBuf; } if (fFlush) return RET_EOF; OutputBuffer(m_pOutHdr, cbInBuf); m_cbOutBufLeft = 0; m_pOutHdr = NULL; if (m_dwCurrentSize >= m_dwDataSize) return RET_EOF; if (m_fSuppress) return RET_EOF; } } else { // PCM 以外 // デコード開始 BYTE bRead[WAV_FILE_BUFF_LEN]; DWORD cbInBuf, cbRead; while (TRUE) { // 停止フラグのチェック if (m_fStop) return RET_STOP; // 出力バッファの確保 if (m_pOutHdr) { OutputBuffer(m_pOutHdr, m_cbOutBuf - m_cbOutBufLeft); m_cbOutBufLeft = 0; m_pOutHdr = NULL; } if (m_fSuppress) return RET_EOF; m_pOutHdr = m_Output.GetBuffer(); m_cbOutBufLeft = m_cbOutBuf; { // Critical Sectionのセット CAutoLock lock(&m_csecThread); if (m_fSeek) { if (m_Status == MAP_STATUS_PLAY) m_fPlay = TRUE; m_Reverb.Reset(); m_Echo.Reset(); m_BassBoost.Reset(); m_Output.Reset(); m_fSeek = FALSE; m_pOutHdr = NULL; acmStreamReset(m_hAcm, 0); continue; } acmStreamSize(m_hAcm, m_cbOutBufLeft, &cbRead, ACM_STREAMSIZEF_DESTINATION); // 読み込み cbRead = min(m_dwDataSize - m_dwCurrentSize, cbRead); cbRead = min(WAV_FILE_BUFF_LEN, cbRead); if (!m_Reader.Read(bRead, cbRead, &cbInBuf) || !cbInBuf) { if (GetLastError() != ERROR_SUCCESS) return RET_ERROR; fFlush = TRUE; } m_dwCurrentSize += cbInBuf; } if (fFlush) return RET_EOF; // ヘッダの確保 ACMSTREAMHEADER ash; memset(&ash, 0, sizeof(ash)); ash.cbStruct = sizeof(ash); //構造体のサイズ ash.pbSrc = bRead; ash.cbSrcLength = cbInBuf; ash.pbDst = (LPBYTE)m_pOutHdr->lpData + (m_cbOutBuf - m_cbOutBufLeft); ash.cbDstLength = m_cbOutBufLeft; if (acmStreamPrepareHeader(m_hAcm, &ash, 0)) break; // 変換 if (acmStreamConvert(m_hAcm, &ash, 0)) break; Preamp((LPBYTE)m_pOutHdr->lpData + (m_cbOutBuf - m_cbOutBufLeft), ash.cbDstLengthUsed); m_cbOutBufLeft -= ash.cbDstLengthUsed; // 後処理 if (acmStreamUnprepareHeader(m_hAcm, &ash, 0)) break; if (m_dwCurrentSize >= m_dwDataSize) return RET_EOF; } return RET_ERROR; } }
static DWORD WINAPI StreamLoop(LPVOID param) { DWORD size,pt; HRESULT hr; char *lpBlockAdd1,*lpBlockAdd2; DWORD blockSize1, blockSize2; ClSoundBuffer *lpSoundBuffer = (ClSoundBuffer *)param; CRITICAL_SECTION cr_section; InitializeCriticalSection(&cr_section); while(TRUE){ pt = WaitForMultipleObjects(3,lpSoundBuffer->hEvent,FALSE,INFINITE); EnterCriticalSection(&cr_section); switch(pt){ case (WAIT_OBJECT_0): case (WAIT_OBJECT_0+1): size = pt -WAIT_OBJECT_0 +1; if(size > 1)size = 0; hr = lpSoundBuffer->lpDSBuffer->Lock(lpSoundBuffer->streamBlockSize*size,lpSoundBuffer->streamBlockSize, (LPVOID*)&lpBlockAdd1, &blockSize1,(LPVOID*)&lpBlockAdd2, &blockSize2, 0); if(DS_OK==hr){ if(WAVE_FORMAT_OGG==lpSoundBuffer->wFormatTag){ char workBuf[4096],outBuf[0x20000]; int rsize,outsize,ret; int remainSize = blockSize1; int writeSize = 0; if(lpSoundBuffer->leakSize){ if(lpSoundBuffer->leakSize > blockSize1){ CopyMemory(lpBlockAdd1,lpSoundBuffer->leakBuff,blockSize1); lpSoundBuffer->leakSize -= blockSize1; MoveMemory(lpSoundBuffer->leakBuff,lpSoundBuffer->leakBuff+blockSize1,lpSoundBuffer->leakSize); remainSize = 0; lpSoundBuffer->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); break; }else{ CopyMemory(lpBlockAdd1,lpSoundBuffer->leakBuff,lpSoundBuffer->leakSize); writeSize += lpSoundBuffer->leakSize; remainSize -= lpSoundBuffer->leakSize; lpSoundBuffer->leakSize = 0; my_deletes(lpSoundBuffer->leakBuff); } } if(lpSoundBuffer->endPt>=0){ ZeroMemory(lpBlockAdd1+writeSize, remainSize); ZeroMemory(lpBlockAdd2, blockSize2); lpSoundBuffer->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); if(pt==lpSoundBuffer->endPt){ lpSoundBuffer->lpDSBuffer->Stop(); goto SoundStop; } break; } rsize = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,workBuf,4096); ret = lpSoundBuffer->o_dat->DecodeOGG(workBuf,rsize,outBuf,0x20000,&outsize); if(ret==OGG_DEC_END){ oggFilEnd: if(1==lpSoundBuffer->repeat){ if(remainSize >= outsize){ CopyMemory(lpBlockAdd1+writeSize, outBuf,outsize); writeSize += outsize; remainSize -= outsize; ZeroMemory(lpBlockAdd1+writeSize, remainSize); if(blockSize2)ZeroMemory(lpBlockAdd2,blockSize2); }else{ CopyMemory(lpBlockAdd1+writeSize, outBuf, remainSize); } lpSoundBuffer->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); if((-1)==lpSoundBuffer->endPt){ lpSoundBuffer->endPt = pt; } break; }else{ if(lpSoundBuffer->repeat) lpSoundBuffer->repeat --; if(lpSoundBuffer->nextStream>=0){ int size; lpSoundBuffer->readFile->StreamCloseFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum); lpSoundBuffer->streamNum = lpSoundBuffer->readFile->StreamOpenFileNum(lpSoundBuffer->arcFileNum,lpSoundBuffer->nextStream,size); lpSoundBuffer->musicNum = lpSoundBuffer->nextStream; lpSoundBuffer->nextStream = -1; } lpSoundBuffer->readFile->StreamSeekFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpSoundBuffer->dataTopOffset,FILE_BEGIN); while(remainSize>=outsize && remainSize>0){ CopyMemory(lpBlockAdd1+writeSize,outBuf,outsize); remainSize -= outsize; writeSize += outsize; if(remainSize > 0){ rsize = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum, workBuf,4096); ret = lpSoundBuffer->o_dat->DecodeOGG(workBuf,rsize,outBuf,0x20000,&outsize); if(OGG_DEC_END==ret){ goto oggFilEnd; } } } if(remainSize){ CopyMemory(lpBlockAdd1+writeSize,outBuf,remainSize); lpSoundBuffer->leakSize = outsize -remainSize; lpSoundBuffer->leakBuff = new BYTE[lpSoundBuffer->leakSize]; CopyMemory(lpSoundBuffer->leakBuff,outBuf +remainSize,lpSoundBuffer->leakSize); } } }else{ while(remainSize>=outsize && remainSize>0){ CopyMemory(lpBlockAdd1+writeSize,outBuf,outsize); remainSize -= outsize; writeSize += outsize; if(remainSize > 0){ rsize = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,workBuf,4096); ret = lpSoundBuffer->o_dat->DecodeOGG(workBuf,rsize,outBuf,0x20000,&outsize); if(OGG_DEC_END==ret){ goto oggFilEnd; } } } if(remainSize){ CopyMemory(lpBlockAdd1+writeSize,outBuf,remainSize); lpSoundBuffer->leakSize = outsize -remainSize; lpSoundBuffer->leakBuff = new BYTE[lpSoundBuffer->leakSize]; CopyMemory(lpSoundBuffer->leakBuff,outBuf +remainSize,lpSoundBuffer->leakSize); } } }else if(NULL==lpSoundBuffer->hAcm){ size = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpBlockAdd1,blockSize1); if(size < blockSize1){ if(1==lpSoundBuffer->repeat){ ZeroMemory(lpBlockAdd1+size,blockSize1-size); lpSoundBuffer->repeat = 0; lpSoundBuffer->lpDSBuffer->Play(0,0,0); }else{ if(lpSoundBuffer->repeat) lpSoundBuffer->repeat --; lpSoundBuffer->readFile->StreamSeekFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpSoundBuffer->dataTopOffset,FILE_BEGIN); lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpBlockAdd1+size,blockSize1-size); } }else{ if(lpSoundBuffer->streamBlockSize>blockSize1){ size = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpBlockAdd2,blockSize2); if(size < blockSize2){ if(1==lpSoundBuffer->repeat){ ZeroMemory(lpBlockAdd2+size,blockSize2-size); lpSoundBuffer->repeat = 0; lpSoundBuffer->lpDSBuffer->Play(0,0,0); }else{ if(lpSoundBuffer->repeat) lpSoundBuffer->repeat --; lpSoundBuffer->readFile->StreamSeekFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpSoundBuffer->dataTopOffset,FILE_BEGIN); lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpBlockAdd2+size,blockSize2-size); } } } } }else{ int remainSize = blockSize1; int writeSize = 0; if(lpSoundBuffer->leakSize){ CopyMemory(lpBlockAdd1,lpSoundBuffer->leakBuff,lpSoundBuffer->leakSize); writeSize += lpSoundBuffer->leakSize; remainSize -= lpSoundBuffer->leakSize; lpSoundBuffer->leakSize = 0; my_deletes(lpSoundBuffer->leakBuff); } size = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum, (char *)lpSoundBuffer->acmSrc.lpStream,lpSoundBuffer->acmSrc.dwStreamSize); if(size < lpSoundBuffer->acmSrc.dwStreamSize){ lpSoundBuffer->ash.cbSrcLength = lpSoundBuffer->ash.dwSrcUser = size; MMRESULT nError = acmStreamConvert(lpSoundBuffer->hAcm,&lpSoundBuffer->ash,0); lpSoundBuffer->ash.cbSrcLength = lpSoundBuffer->ash.dwSrcUser = lpSoundBuffer->acmSrc.dwStreamSize; if(1==lpSoundBuffer->repeat){ if(0==nError){ if(remainSize >= lpSoundBuffer->ash.cbDstLengthUsed){ CopyMemory(lpBlockAdd1+writeSize, lpSoundBuffer->acmDst.lpStream, lpSoundBuffer->ash.cbDstLengthUsed); writeSize += lpSoundBuffer->ash.cbDstLengthUsed; remainSize -= lpSoundBuffer->ash.cbDstLengthUsed; ZeroMemory(lpBlockAdd1+writeSize, remainSize); if(blockSize2)ZeroMemory(lpBlockAdd2,blockSize2); }else{ CopyMemory(lpBlockAdd1+writeSize, lpSoundBuffer->acmDst.lpStream, remainSize); CopyMemory(lpBlockAdd2, lpSoundBuffer->acmDst.lpStream +remainSize,lpSoundBuffer->ash.cbDstLengthUsed -remainSize); if(blockSize2 > lpSoundBuffer->ash.cbDstLengthUsed -remainSize){ ZeroMemory(lpBlockAdd2 +(lpSoundBuffer->ash.cbDstLengthUsed -remainSize),blockSize2-(lpSoundBuffer->ash.cbDstLengthUsed -remainSize)); } } lpSoundBuffer->repeat = 0; lpSoundBuffer->lpDSBuffer->Play(0,0,0); } }else{ if(lpSoundBuffer->repeat) lpSoundBuffer->repeat --; lpSoundBuffer->readFile->StreamSeekFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum,lpSoundBuffer->dataTopOffset,FILE_BEGIN); if(0==nError){ while(remainSize>=lpSoundBuffer->ash.cbDstLengthUsed && remainSize>0){ CopyMemory(lpBlockAdd1+writeSize,lpSoundBuffer->acmDst.lpStream,lpSoundBuffer->ash.cbDstLengthUsed); remainSize -= lpSoundBuffer->ash.cbDstLengthUsed; writeSize += lpSoundBuffer->ash.cbDstLengthUsed; if(remainSize > 0){ size = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum, (char *)lpSoundBuffer->acmSrc.lpStream,lpSoundBuffer->acmSrc.dwStreamSize); nError = acmStreamConvert(lpSoundBuffer->hAcm,&lpSoundBuffer->ash,ACM_STREAMCONVERTF_BLOCKALIGN); } } if(remainSize){ CopyMemory(lpBlockAdd1+writeSize,lpSoundBuffer->acmDst.lpStream,remainSize); lpSoundBuffer->leakSize = lpSoundBuffer->ash.cbDstLengthUsed -remainSize; lpSoundBuffer->leakBuff = new BYTE[lpSoundBuffer->leakSize]; CopyMemory(lpSoundBuffer->leakBuff,lpSoundBuffer->acmDst.lpStream +remainSize,lpSoundBuffer->leakSize); } } } }else{ MMRESULT nError = acmStreamConvert(lpSoundBuffer->hAcm,&lpSoundBuffer->ash, ACM_STREAMCONVERTF_BLOCKALIGN); if(0==nError){ while(remainSize>=lpSoundBuffer->ash.cbDstLengthUsed && remainSize>0){ CopyMemory(lpBlockAdd1+writeSize,lpSoundBuffer->acmDst.lpStream,lpSoundBuffer->ash.cbDstLengthUsed); remainSize -= lpSoundBuffer->ash.cbDstLengthUsed; writeSize += lpSoundBuffer->ash.cbDstLengthUsed; if(remainSize > 0){ size = lpSoundBuffer->readFile->StreamReadFile(lpSoundBuffer->arcFileNum,lpSoundBuffer->streamNum, (char *)lpSoundBuffer->acmSrc.lpStream,lpSoundBuffer->acmSrc.dwStreamSize); nError = acmStreamConvert(lpSoundBuffer->hAcm,&lpSoundBuffer->ash, ACM_STREAMCONVERTF_BLOCKALIGN); } } if(remainSize){ CopyMemory(lpBlockAdd1+writeSize,lpSoundBuffer->acmDst.lpStream,remainSize); lpSoundBuffer->leakSize = lpSoundBuffer->ash.cbDstLengthUsed -remainSize; lpSoundBuffer->leakBuff = new BYTE[lpSoundBuffer->leakSize]; CopyMemory(lpSoundBuffer->leakBuff,lpSoundBuffer->acmDst.lpStream +remainSize,lpSoundBuffer->leakSize); } } } } lpSoundBuffer->lpDSBuffer->Unlock(lpBlockAdd1, blockSize1, lpBlockAdd2, blockSize2); } break; default: SoundStop: lpSoundBuffer->repeat = 0; lpSoundBuffer->lpDSNotify->Release(); lpSoundBuffer->lpDSNotify = NULL; CloseHandle(lpSoundBuffer->hEvent[0]); CloseHandle(lpSoundBuffer->hEvent[1]); CloseHandle(lpSoundBuffer->hEvent[2]); lpSoundBuffer->hEvent[0] = lpSoundBuffer->hEvent[1] = lpSoundBuffer->hEvent[2] = NULL; lpSoundBuffer->status = PCM_STOP; LeaveCriticalSection(&cr_section); DeleteCriticalSection(&cr_section); CloseHandle(lpSoundBuffer->hLoopThread); lpSoundBuffer->hLoopThread = NULL; ExitThread(TRUE); return 0L; } LeaveCriticalSection(&cr_section); } DeleteCriticalSection(&cr_section); ExitThread(TRUE); return 0L; } // StreamLoop
static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start, LONG samples, LPVOID buffer, LONG buffersize, LPLONG bytesread, LPLONG samplesread) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; HRESULT hr; DWORD size; TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer, buffersize, bytesread, samplesread); /* clear return parameters if given */ if (bytesread != NULL) *bytesread = 0; if (samplesread != NULL) *samplesread = 0; /* Do we have our compressor? */ if (This->has == NULL) { hr = AVIFILE_OpenCompressor(This); if (FAILED(hr)) return hr; } /* only need to pass through? */ if (This->cbInFormat == This->cbOutFormat && memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) { return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize, bytesread, samplesread); } /* read as much as fit? */ if (samples == -1) samples = buffersize / This->lpOutFormat->nBlockAlign; /* limit to buffersize */ if (samples * This->lpOutFormat->nBlockAlign > buffersize) samples = buffersize / This->lpOutFormat->nBlockAlign; /* only return needed size? */ if (buffer == NULL || buffersize <= 0 || samples == 0) { if (bytesread == NULL && samplesread == NULL) return AVIERR_BADPARAM; if (bytesread != NULL) *bytesread = samples * This->lpOutFormat->nBlockAlign; if (samplesread != NULL) *samplesread = samples; return AVIERR_OK; } /* map our positions to pStream positions */ CONVERT_THIS_to_STREAM(&start); /* our needed internal buffersize */ size = samples * This->lpInFormat->nBlockAlign; /* Need to free destination buffer used for writing? */ if (This->acmStreamHdr.pbDst != NULL) { HeapFree(GetProcessHeap(), 0, This->acmStreamHdr.pbDst); This->acmStreamHdr.pbDst = NULL; This->acmStreamHdr.dwDstUser = 0; } /* need bigger source buffer? */ if (This->acmStreamHdr.pbSrc == NULL || This->acmStreamHdr.dwSrcUser < size) { if (This->acmStreamHdr.pbSrc == NULL) This->acmStreamHdr.pbSrc = HeapAlloc(GetProcessHeap(), 0, size); else This->acmStreamHdr.pbSrc = HeapReAlloc(GetProcessHeap(), 0, This->acmStreamHdr.pbSrc, size); if (This->acmStreamHdr.pbSrc == NULL) return AVIERR_MEMORY; This->acmStreamHdr.dwSrcUser = size; } This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr); This->acmStreamHdr.cbSrcLengthUsed = 0; This->acmStreamHdr.cbDstLengthUsed = 0; This->acmStreamHdr.cbSrcLength = size; /* read source data */ hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc, This->acmStreamHdr.cbSrcLength, (LONG *)&This->acmStreamHdr.cbSrcLength, NULL); if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0) return hr; /* need to prepare stream? */ This->acmStreamHdr.pbDst = buffer; This->acmStreamHdr.cbDstLength = buffersize; if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) { if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) { This->acmStreamHdr.pbDst = NULL; This->acmStreamHdr.cbDstLength = 0; return AVIERR_COMPRESSOR; } } /* now do the conversion */ /* FIXME: use ACM_CONVERTF_* flags */ if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK) hr = AVIERR_COMPRESSOR; This->acmStreamHdr.pbDst = NULL; This->acmStreamHdr.cbDstLength = 0; /* fill out return parameters if given */ if (bytesread != NULL) *bytesread = This->acmStreamHdr.cbDstLengthUsed; if (samplesread != NULL) *samplesread = This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign; return hr; }