Resampler.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author: Ben Allison [email protected]
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include "Resampler.h"
  10. #include <ks.h>
  11. #include <ksmedia.h>
  12. static int GetChannelMask(size_t channels)
  13. {
  14. switch(channels)
  15. {
  16. case 1: return KSAUDIO_SPEAKER_MONO;
  17. case 2: return KSAUDIO_SPEAKER_STEREO;
  18. case 4: return KSAUDIO_SPEAKER_SURROUND;
  19. case 6: return KSAUDIO_SPEAKER_5POINT1;
  20. case 8: return KSAUDIO_SPEAKER_7POINT1;
  21. default: return 0;
  22. }
  23. }
  24. static void FillWFX_float(WAVEFORMATIEEEFLOATEX *format, size_t channels, size_t bits, size_t sampleRate)
  25. {
  26. ZeroMemory(format, sizeof(WAVEFORMATIEEEFLOATEX));
  27. size_t padded_bits = (bits + 7) & (~7);
  28. format->Format.nChannels = (WORD)channels;
  29. format->Format.nSamplesPerSec = (DWORD)sampleRate;
  30. format->Format.nAvgBytesPerSec = (DWORD)(sampleRate * channels * (padded_bits >> 3));
  31. format->Format.nBlockAlign = (WORD)(channels * (padded_bits >> 3));
  32. format->Format.wBitsPerSample = (WORD)padded_bits;
  33. format->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  34. format->Format.cbSize = sizeof(WAVEFORMATIEEEFLOATEX) - sizeof(WAVEFORMATEX);
  35. format->Samples.wValidBitsPerSample = (WORD)bits;
  36. format->dwChannelMask = GetChannelMask(channels);
  37. format->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
  38. }
  39. static void FillWFX(WAVEFORMATEXTENSIBLE *format, size_t channels, size_t bits, size_t sampleRate)
  40. {
  41. ZeroMemory(format, sizeof(WAVEFORMATEXTENSIBLE));
  42. size_t padded_bits = (bits + 7) & (~7);
  43. format->Format.nChannels = (WORD)channels;
  44. format->Format.nSamplesPerSec = (DWORD)sampleRate;
  45. format->Format.nAvgBytesPerSec = (DWORD)(sampleRate * channels * (padded_bits >> 3));
  46. format->Format.nBlockAlign = (WORD)(channels * (padded_bits >> 3));
  47. format->Format.wBitsPerSample = (WORD)padded_bits;
  48. if (channels > 2 || padded_bits != bits)
  49. {
  50. format->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
  51. format->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
  52. format->Samples.wValidBitsPerSample = (WORD)bits;
  53. format->dwChannelMask = GetChannelMask(channels);
  54. format->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  55. }
  56. else
  57. {
  58. format->Format.wFormatTag = WAVE_FORMAT_PCM;
  59. format->Format.cbSize = 0;
  60. }
  61. }
  62. Resampler::Resampler(size_t inputBits, size_t inputChannels, size_t inputSampleRate,
  63. size_t outputBits, size_t outputChannels, size_t outputSampleRate, bool floatingPoint)
  64. : sizeFactor(1.), hStream(0), buffer(0), eof(false)
  65. {
  66. if (floatingPoint)
  67. {
  68. WAVEFORMATIEEEFLOATEX inputFormat;
  69. FillWFX_float(&inputFormat, inputChannels, inputBits, inputSampleRate);
  70. WAVEFORMATIEEEFLOATEX outputFormat;
  71. FillWFX_float(&outputFormat, outputChannels, outputBits, outputSampleRate);
  72. acmStreamOpen(&hStream, 0, &inputFormat.Format, &outputFormat.Format, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME);
  73. }
  74. else
  75. {
  76. WAVEFORMATEXTENSIBLE inputFormat = {0};
  77. FillWFX(&inputFormat, inputChannels, inputBits, inputSampleRate);
  78. WAVEFORMATEXTENSIBLE outputFormat = {0};
  79. FillWFX(&outputFormat, outputChannels, outputBits, outputSampleRate);
  80. acmStreamOpen(&hStream, 0, &inputFormat.Format, &outputFormat.Format, 0, 0, 0, ACM_STREAMOPENF_NONREALTIME);
  81. }
  82. if (!hStream)
  83. {
  84. // error - what should we do?
  85. return ;
  86. }
  87. bufferAlloc = MulDiv(1024, (int) (outputBits * outputChannels), 8); // TODO: use acmStreamSize
  88. buffer = (__int8 *)calloc(bufferAlloc, sizeof(__int8));
  89. bufferValid = 0;
  90. sizeFactor = (outputChannels * outputBits * outputSampleRate) * (inputChannels * inputBits * inputSampleRate);
  91. }
  92. Resampler::~Resampler()
  93. {
  94. if (hStream)
  95. {
  96. acmStreamClose(hStream, 0);
  97. }
  98. free(buffer);
  99. }
  100. size_t Resampler::UseInternalBuffer(void *output, size_t outputBytes)
  101. {
  102. if (bufferValid)
  103. {
  104. size_t writeSize = min(outputBytes, bufferValid);
  105. memcpy(output, buffer, writeSize);
  106. if (writeSize)
  107. memmove(buffer, buffer + writeSize, bufferValid - writeSize);
  108. bufferValid -= writeSize;
  109. return writeSize;
  110. }
  111. else
  112. return 0;
  113. }
  114. void Resampler::Flush()
  115. {
  116. eof = true;
  117. }
  118. size_t Resampler::Convert(void *input, size_t *inputBytes, void *output, size_t outputBytes)
  119. {
  120. size_t x = UseInternalBuffer(output, outputBytes);
  121. if (x)
  122. return x;
  123. ACMSTREAMHEADER streamHeader;
  124. ZeroMemory(&streamHeader, sizeof(streamHeader));
  125. streamHeader.cbStruct = sizeof(streamHeader);
  126. streamHeader.pbSrc = reinterpret_cast<LPBYTE>(input);
  127. streamHeader.cbSrcLength = (DWORD)*inputBytes;
  128. streamHeader.pbDst = reinterpret_cast<LPBYTE>(buffer);
  129. streamHeader.cbDstLength = (DWORD)bufferAlloc;
  130. if (acmStreamPrepareHeader(hStream, &streamHeader, 0))
  131. return 0; // m_error = 1;
  132. if (input && *inputBytes && !eof)
  133. acmStreamConvert(hStream, &streamHeader, ACM_STREAMCONVERTF_BLOCKALIGN);
  134. else
  135. acmStreamConvert(hStream, &streamHeader, ACM_STREAMCONVERTF_END);
  136. *inputBytes -= streamHeader.cbSrcLengthUsed;
  137. bufferValid = streamHeader.cbDstLengthUsed;
  138. acmStreamUnprepareHeader(hStream, &streamHeader, 0);
  139. return UseInternalBuffer(output, outputBytes);
  140. }
  141. bool Resampler::OK()
  142. {
  143. if (hStream)
  144. return true;
  145. else
  146. return false;
  147. }