BOOL GetFormatDescription ( LPWAVEFORMATEX pwformat, LPTSTR pszFormatTag, LPTSTR pszFormat) { MMRESULT mmr; // Retrieve the descriptive name for the FormatTag in pwformat. if (NULL != pszFormatTag) { ACMFORMATTAGDETAILS aftd; memset(&aftd, 0, sizeof(aftd)); // Fill in the required members FormatTAG query. aftd.cbStruct = sizeof(aftd); aftd.dwFormatTag = pwformat->wFormatTag; // Ask ACM to find first available driver that supports the specified Format tag. mmr = acmFormatTagDetails(NULL, &aftd, ACM_FORMATTAGDETAILSF_FORMATTAG); if (MMSYSERR_NOERROR != mmr) { return (FALSE); } // Copy the Format tag name into the calling application's // buffer. lstrcpy(pszFormatTag, aftd.szFormatTag); } CString formatstr; CString str_samples_per_second; CString str_bits_per_sample; CString str_avg_bytes_per_second; CString str_nchannels; str_samples_per_second.Format("%d Hz",pwformat->nSamplesPerSec); str_bits_per_sample.Format("%d Bit",pwformat->wBitsPerSample); str_avg_bytes_per_second.Format("%d Bytes/sec",pwformat->nAvgBytesPerSec); if (pwformat->nChannels==1) str_nchannels.Format("Mono"); else str_nchannels.Format("Stereo"); formatstr = str_samples_per_second + ", "; if ((pwformat->wBitsPerSample)>0) formatstr = formatstr + str_bits_per_sample + ", "; formatstr = formatstr + str_nchannels + " " + str_avg_bytes_per_second; lstrcpy(pszFormat, LPCTSTR(formatstr)); return (TRUE); }
BOOL CALLBACK acmDriverEnumCallback( HACMDRIVERID hadid, DWORD dwInstance, DWORD fdwSupport ){ MMRESULT mmr; HACMDRIVER driver; int i; ACMDRIVERDETAILS details; details.cbStruct = sizeof(ACMDRIVERDETAILS); mmr = acmDriverDetails( hadid, &details, 0 ); mmr = acmDriverOpen( &driver, hadid, 0 ); for(i = 0; i < details.cFormatTags; i++ ){ ACMFORMATTAGDETAILS fmtDetails; ZeroMemory( &fmtDetails, sizeof(fmtDetails) ); fmtDetails.cbStruct = sizeof(ACMFORMATTAGDETAILS); fmtDetails.dwFormatTagIndex = i; mmr = acmFormatTagDetails( driver, &fmtDetails, ACM_FORMATTAGDETAILSF_INDEX ); if( fdwSupport & ACMDRIVERDETAILS_SUPPORTF_CODEC ) { /* fprintf(stderr, "supported codec: %s\n" ,details.szLongName ); */ if( fmtDetails.dwFormatTag == WAVE_FORMAT_MSG723 ) { g_g723Drivers = /* 1 */ 0; /* ! fprintf(stderr, "Find Codec %s\n" ,details.szLongName ); */ #if 0 fprintf(stderr, "G723 cFormatTags %i\n" ,details.cFormatTags ); fprintf(stderr, "G723 cFilterTags %i\n" ,details.cFilterTags); #endif return -1; } else if( fmtDetails.dwFormatTag == WAVE_FORMAT_GSM610 ) { g_gsmDrivers = 1; /* ! fprintf(stderr, "Find Codec %s\n" ,details.szLongName ); */ return -1; } } else { /* ! fprintf(stderr, "Unsupported codec: %s\n" ,details.szLongName ); */ } } mmr = acmDriverClose( driver, 0 ); return -1; }
CACMWaveFormat::CACMWaveFormat(WORD fmt, DWORD sz) { MMRESULT mmr; m_fmt = NULL; m_size = 0; if (0 == sz) { CACMStruct<ACMFORMATTAGDETAILS> tagD; // WIN95 bug keeps us from using the correct fmt here, // because acmFormatEnum fails later if not tagD->dwFormatTag = WAVE_FORMAT_UNKNOWN; mmr = acmFormatTagDetails(NULL, tagD, ACM_FORMATTAGDETAILSF_LARGESTSIZE ); if (0 != mmr) raiseError(mmr, "Error getting format descriptor size"); sz = tagD->cbFormatSize; } m_fmt = (LPWAVEFORMATEX) GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, sz); if (m_fmt) { m_fmt->wFormatTag = fmt; m_size = sz; } else { raiseError(MMSYSERR_NOMEM, "No memory for wave format descriptor"); } }
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); }