123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /** (c) Nullsoft, Inc. C O N F I D E N T I A L
- ** Filename:
- ** Project:
- ** Description:
- ** Author: Ben Allison [email protected]
- ** Created:
- **/
- #include "main.h"
- #include "Resampler.h"
- #include <ks.h>
- #include <ksmedia.h>
- static int GetChannelMask(size_t channels)
- {
- switch(channels)
- {
- case 1: return KSAUDIO_SPEAKER_MONO;
- case 2: return KSAUDIO_SPEAKER_STEREO;
- case 4: return KSAUDIO_SPEAKER_SURROUND;
- case 6: return KSAUDIO_SPEAKER_5POINT1;
- case 8: return KSAUDIO_SPEAKER_7POINT1;
- default: return 0;
- }
- }
- static void FillWFX_float(WAVEFORMATIEEEFLOATEX *format, size_t channels, size_t bits, size_t sampleRate)
- {
- ZeroMemory(format, sizeof(WAVEFORMATIEEEFLOATEX));
- size_t padded_bits = (bits + 7) & (~7);
- format->Format.nChannels = (WORD)channels;
- format->Format.nSamplesPerSec = (DWORD)sampleRate;
- format->Format.nAvgBytesPerSec = (DWORD)(sampleRate * channels * (padded_bits >> 3));
- format->Format.nBlockAlign = (WORD)(channels * (padded_bits >> 3));
- format->Format.wBitsPerSample = (WORD)padded_bits;
- format->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- format->Format.cbSize = sizeof(WAVEFORMATIEEEFLOATEX) - sizeof(WAVEFORMATEX);
- format->Samples.wValidBitsPerSample = (WORD)bits;
- format->dwChannelMask = GetChannelMask(channels);
- format->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
- }
- static void FillWFX(WAVEFORMATEXTENSIBLE *format, size_t channels, size_t bits, size_t sampleRate)
- {
- ZeroMemory(format, sizeof(WAVEFORMATEXTENSIBLE));
- size_t padded_bits = (bits + 7) & (~7);
- format->Format.nChannels = (WORD)channels;
- format->Format.nSamplesPerSec = (DWORD)sampleRate;
- format->Format.nAvgBytesPerSec = (DWORD)(sampleRate * channels * (padded_bits >> 3));
- format->Format.nBlockAlign = (WORD)(channels * (padded_bits >> 3));
- format->Format.wBitsPerSample = (WORD)padded_bits;
- if (channels > 2 || padded_bits != bits)
- {
- format->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- format->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
- format->Samples.wValidBitsPerSample = (WORD)bits;
- format->dwChannelMask = GetChannelMask(channels);
- format->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- }
- else
- {
- format->Format.wFormatTag = WAVE_FORMAT_PCM;
- format->Format.cbSize = 0;
- }
- }
- Resampler::Resampler(size_t inputBits, size_t inputChannels, size_t inputSampleRate,
- size_t outputBits, size_t outputChannels, size_t outputSampleRate, bool floatingPoint)
- : sizeFactor(1.), hStream(0), buffer(0), eof(false)
- {
- if (floatingPoint)
- {
- WAVEFORMATIEEEFLOATEX inputFormat;
- FillWFX_float(&inputFormat, inputChannels, inputBits, inputSampleRate);
- WAVEFORMATIEEEFLOATEX outputFormat;
- FillWFX_float(&outputFormat, outputChannels, outputBits, outputSampleRate);
- acmStreamOpen(&hStream, 0, &inputFormat.Format, &outputFormat.Format, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME);
- }
- else
- {
- WAVEFORMATEXTENSIBLE inputFormat = {0};
- FillWFX(&inputFormat, inputChannels, inputBits, inputSampleRate);
- WAVEFORMATEXTENSIBLE outputFormat = {0};
- FillWFX(&outputFormat, outputChannels, outputBits, outputSampleRate);
- acmStreamOpen(&hStream, 0, &inputFormat.Format, &outputFormat.Format, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME);
- }
- if (!hStream)
- {
- // error - what should we do?
- return ;
- }
- bufferAlloc = MulDiv(1024, (int) (outputBits * outputChannels), 8); // TODO: use acmStreamSize
- buffer = (__int8 *)calloc(bufferAlloc, sizeof(__int8));
- bufferValid = 0;
- sizeFactor = (outputChannels * outputBits * outputSampleRate) * (inputChannels * inputBits * inputSampleRate);
- }
- Resampler::~Resampler()
- {
- if (hStream)
- {
- acmStreamClose(hStream, 0);
- }
- free(buffer);
- }
- size_t Resampler::UseInternalBuffer(void *output, size_t outputBytes)
- {
- if (bufferValid)
- {
- size_t writeSize = min(outputBytes, bufferValid);
- memcpy(output, buffer, writeSize);
- if (writeSize)
- memmove(buffer, buffer + writeSize, bufferValid - writeSize);
- bufferValid -= writeSize;
- return writeSize;
- }
- else
- return 0;
- }
- void Resampler::Flush()
- {
- eof = true;
- }
- size_t Resampler::Convert(void *input, size_t *inputBytes, void *output, size_t outputBytes)
- {
- size_t x = UseInternalBuffer(output, outputBytes);
- if (x)
- return x;
- ACMSTREAMHEADER streamHeader;
- ZeroMemory(&streamHeader, sizeof(streamHeader));
- streamHeader.cbStruct = sizeof(streamHeader);
- streamHeader.pbSrc = reinterpret_cast<LPBYTE>(input);
- streamHeader.cbSrcLength = (DWORD)*inputBytes;
- streamHeader.pbDst = reinterpret_cast<LPBYTE>(buffer);
- streamHeader.cbDstLength = (DWORD)bufferAlloc;
- if (acmStreamPrepareHeader(hStream, &streamHeader, 0))
- return 0; // m_error = 1;
- if (input && *inputBytes && !eof)
- acmStreamConvert(hStream, &streamHeader, ACM_STREAMCONVERTF_BLOCKALIGN);
- else
- acmStreamConvert(hStream, &streamHeader, ACM_STREAMCONVERTF_END);
- *inputBytes -= streamHeader.cbSrcLengthUsed;
- bufferValid = streamHeader.cbDstLengthUsed;
- acmStreamUnprepareHeader(hStream, &streamHeader, 0);
- return UseInternalBuffer(output, outputBytes);
- }
- bool Resampler::OK()
- {
- if (hStream)
- return true;
- else
- return false;
- }
|