static HRESULT CreateAudioMediaType(const WWMFPcmFormat &fmt, IMFMediaType** ppMediaType) { HRESULT hr; IMFMediaType *pMediaType = NULL; *ppMediaType = NULL; HRG(MFCreateMediaType(&pMediaType) ); HRG(pMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio)); HRG(pMediaType->SetGUID(MF_MT_SUBTYPE, (fmt.sampleFormat == WWMFBitFormatInt) ? MFAudioFormat_PCM : MFAudioFormat_Float)); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, fmt.nChannels)); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, fmt.sampleRate)); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, fmt.FrameBytes())); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, fmt.BytesPerSec())); HRG(pMediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, fmt.bits)); HRG(pMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); if (0 != fmt.dwChannelMask) { HRG(pMediaType->SetUINT32(MF_MT_AUDIO_CHANNEL_MASK, fmt.dwChannelMask)); } if (fmt.bits != fmt.validBitsPerSample) { HRG(pMediaType->SetUINT32(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, fmt.validBitsPerSample)); } *ppMediaType = pMediaType; pMediaType = NULL; //< prevent release end: SafeRelease(&pMediaType); return hr; }
static HRESULT WriteWavHeader(FILE *fpw, WWMFPcmFormat &format, DWORD dataBytes) { HRESULT hr = E_FAIL; int dataChunkSize = ((dataBytes+1)&(~1)) + 4; HRG(WriteBytes(fpw, "RIFF", 4U)); HRG(WriteInt32(fpw, dataChunkSize + 0x24)); HRG(WriteBytes(fpw, "WAVE", 4U)); HRG(WriteBytes(fpw, "fmt ", 4U)); HRG(WriteInt32(fpw, 16)); // fmt audioFormat size==2 1==int 3==float switch (format.sampleFormat) { case WWMFBitFormatInt: HRG(WriteInt16(fpw, 1)); break; case WWMFBitFormatFloat: HRG(WriteInt16(fpw, 3)); break; default: goto end; } // fmt numChannels size==2 HRG(WriteInt16(fpw, format.nChannels)); // fmt sampleRate size==4 HRG(WriteInt32(fpw, format.sampleRate)); // fmt byteRate size==4 HRG(WriteInt32(fpw, format.BytesPerSec())); // fmt blockAlign size==2 HRG(WriteInt16(fpw, format.FrameBytes())); // fmt bitspersample size==2 HRG(WriteInt16(fpw, format.bits)); HRG(WriteBytes(fpw, "data", 4U)); HRG(WriteInt32(fpw, dataChunkSize)); end: return hr; }
int wmain(int argc, wchar_t *argv[]) { // _CrtSetBreakAlloc(35); // COM leak cannot be detected by debug heap manager ... _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); HRESULT hr = S_OK; bool bCoInitialize = false; FILE *fpr = NULL; FILE *fpw = NULL; errno_t ercd; BYTE *buff = NULL; DWORD buffBytes = 0; DWORD readBytes = 0; DWORD remainBytes = 0; DWORD expectedOutputDataBytes = 0; DWORD result = 0; DWORD writeDataTotalBytes = 0; int conversionQuality = 60; WWMFResampler resampler; WWMFPcmFormat inputFormat; WWMFPcmFormat outputFormat; WWMFSampleData sampleData; if (argc != 6) { PrintUsage(argv[0]); return 1; } HRG(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)); bCoInitialize = true; ercd = _wfopen_s(&fpr, argv[1], L"rb"); if (0 != ercd) { printf("file open error %S\n", argv[1]); PrintUsage(argv[0]); hr = E_FAIL; goto end; } ercd = _wfopen_s(&fpw, argv[2], L"wb"); if (0 != ercd) { printf("file open error %S\n", argv[2]); PrintUsage(argv[0]); hr = E_FAIL; goto end; } HRG(ReadWavHeader(fpr, &inputFormat, &remainBytes)); outputFormat = inputFormat; outputFormat.sampleRate = _wtoi(argv[3]); outputFormat.bits = (short)_wtoi(argv[4]); conversionQuality = _wtoi(argv[5]); if (0 == outputFormat.sampleRate || 0 == conversionQuality) { PrintUsage(argv[0]); hr = E_FAIL; goto end; } outputFormat.validBitsPerSample = outputFormat.bits; switch (outputFormat.bits) { case 16: case 24: outputFormat.sampleFormat = WWMFBitFormatInt; break; case 32: outputFormat.sampleFormat = WWMFBitFormatFloat; break; default: PrintUsage(argv[0]); hr = E_FAIL; goto end; } expectedOutputDataBytes = (int64_t)remainBytes * outputFormat.BytesPerSec() / inputFormat .BytesPerSec(); HRG(WriteWavHeader(fpw, outputFormat, expectedOutputDataBytes)); HRG(resampler.Initialize(inputFormat, outputFormat, conversionQuality)); buffBytes = 128 * 1024 * inputFormat.FrameBytes(); buff = new BYTE[buffBytes]; for (;;) { // read PCM data from file readBytes = buffBytes; if (remainBytes < readBytes) { readBytes = remainBytes; } remainBytes -= readBytes; result = fread(buff, 1, readBytes, fpr); if (result != readBytes) { printf("file read error\n"); hr = E_FAIL; goto end; } // convert HRG(resampler.Resample(buff, readBytes, &sampleData)); // write to file result = fwrite(sampleData.data, 1, sampleData.bytes, fpw); if (result != sampleData.bytes) { printf("file write error\n"); hr = E_FAIL; goto end; } writeDataTotalBytes += sampleData.bytes; sampleData.Release(); if (remainBytes == 0) { // end HRG(resampler.Drain(buffBytes, &sampleData)); // write remaining PCM data to file result = fwrite(sampleData.data, 1, sampleData.bytes, fpw); if (result != sampleData.bytes) { printf("file write error\n"); hr = E_FAIL; goto end; } writeDataTotalBytes += sampleData.bytes; sampleData.Release(); break; } } // data chunk align is 2 bytes if (writeDataTotalBytes & 1) { if (0 != fputc(0, fpw)) { printf("file write error\n"); hr = E_FAIL; goto end; } ++writeDataTotalBytes; } HRG(FixWavHeader(fpw, writeDataTotalBytes)); hr = S_OK; end: resampler.Finalize(); if (bCoInitialize) { CoUninitialize(); bCoInitialize = false; } delete[] buff; buff = NULL; if (fpw != NULL) { fclose(fpw); fpw = NULL; } if (fpr != NULL) { fclose(fpr); fpr = NULL; } return SUCCEEDED(hr) ? 0 : 1; }