ExtendedRead.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "main.h"
  2. #include "ExtendedRead.h"
  3. extern WM_MEDIA_TYPE *NewMediaType(IWMOutputMediaProps *props);
  4. ExtendedReadStruct::ExtendedReadStruct() : buffer(0), reader(0), streamNum(0), bufferUsed(0), endOfFile(false), length(0)
  5. {}
  6. ExtendedReadStruct::ExtendedReadStruct(IWMSyncReader *_reader) : buffer(0), reader(0), streamNum(0), bufferUsed(0), endOfFile(false), length(0)
  7. {
  8. reader = _reader;
  9. reader->AddRef();
  10. }
  11. #define CBCLASS ExtendedReadStruct
  12. START_DISPATCH;
  13. CB(IFC_AUDIOSTREAM_READAUDIO, ReadAudio)
  14. END_DISPATCH;
  15. ExtendedReadStruct::~ExtendedReadStruct()
  16. {
  17. if (reader)
  18. {
  19. reader->Close();
  20. reader->Release();
  21. }
  22. if (buffer)
  23. buffer->Release();
  24. }
  25. size_t ExtendedReadStruct::ReadAudio(void *_buffer, size_t len)
  26. {
  27. __int8 *dest = reinterpret_cast<__int8 *>(_buffer);
  28. int bytesCopied = 0;
  29. /*
  30. while we still have bytes left
  31. {
  32. read a buffer
  33. copy buffer to user passed buffer
  34. if we have stuff left in the buffer, save it and return
  35. if we hit EOF, return
  36. }
  37. */
  38. size_t frameSize = (BitSize()/8)*Channels();
  39. len -= (len % frameSize); // only do whole frames
  40. while (len)
  41. {
  42. if (buffer)
  43. {
  44. BYTE *bufferBytes;
  45. DWORD bufferTotal;
  46. buffer->GetBufferAndLength(&bufferBytes, &bufferTotal);
  47. if (bufferUsed < bufferTotal)
  48. {
  49. size_t toCopy = min(bufferTotal - bufferUsed, len);
  50. memcpy(dest, bufferBytes + bufferUsed, toCopy);
  51. bufferUsed += toCopy;
  52. len -= toCopy;
  53. dest += toCopy;
  54. bytesCopied += toCopy;
  55. if (bufferUsed == bufferTotal)
  56. {
  57. bufferUsed = 0;
  58. buffer->Release();
  59. buffer = 0;
  60. }
  61. }
  62. }
  63. else if (!endOfFile)
  64. {
  65. QWORD sampleTime, duration;
  66. DWORD flags;
  67. DWORD outputNum;
  68. WORD streamNum2;
  69. HRESULT hr;
  70. hr = reader->GetNextSample(streamNum, &buffer, &sampleTime, &duration, &flags, & outputNum, &streamNum2);
  71. if (hr == NS_E_NO_MORE_SAMPLES)
  72. endOfFile = true;
  73. }
  74. else
  75. return bytesCopied;
  76. }
  77. return bytesCopied;
  78. }
  79. bool ExtendedReadStruct::Open(const wchar_t *filename)
  80. {
  81. //mod.InitWM();
  82. if (!reader)
  83. {
  84. if (!SUCCEEDED(WMCreateSyncReader(NULL, 0, &reader)))
  85. {
  86. reader = 0;
  87. return false;
  88. }
  89. }
  90. if (SUCCEEDED(reader->Open(filename)))
  91. {
  92. return true;
  93. }
  94. else
  95. {
  96. reader->Release();
  97. reader = 0;
  98. return false;
  99. }
  100. }
  101. bool ExtendedReadStruct::FindOutput(int bits, int channels)
  102. {
  103. DWORD numOutputs, output, format, numFormats;
  104. IWMOutputMediaProps *formatProperties;
  105. GUID mediaType;
  106. DWORD audioOutputNum;
  107. if (FAILED((reader->GetOutputCount(&numOutputs))))
  108. return false;
  109. for (output = 0;output < numOutputs;output++)
  110. {
  111. HRESULT hr;
  112. DWORD speakerConfig;
  113. switch (channels)
  114. {
  115. case 1:
  116. speakerConfig = DSSPEAKER_MONO;
  117. break;
  118. case 2:
  119. speakerConfig = DSSPEAKER_STEREO;
  120. break;
  121. case 0:
  122. default:
  123. speakerConfig = config_audio_num_channels; // TODO: force max channels?
  124. }
  125. hr = reader->SetOutputSetting(output, g_wszSpeakerConfig, WMT_TYPE_DWORD, (BYTE *) & speakerConfig, sizeof(speakerConfig));
  126. assert(hr == S_OK);
  127. BOOL discreteChannels = TRUE;
  128. hr = reader->SetOutputSetting(output, g_wszEnableDiscreteOutput, WMT_TYPE_BOOL, (BYTE *) & discreteChannels , sizeof(discreteChannels));
  129. assert(hr == S_OK);
  130. if (FAILED(reader->GetOutputFormatCount(output, &numFormats)))
  131. continue;
  132. for (format = 0;format < numFormats;format++)
  133. {
  134. reader->GetOutputFormat(output, format, &formatProperties);
  135. formatProperties->GetType(&mediaType);
  136. if (mediaType != WMMEDIATYPE_Audio)
  137. continue;
  138. WM_MEDIA_TYPE *mediaType = NewMediaType(formatProperties);
  139. if (mediaType->subtype == WMMEDIASUBTYPE_PCM)
  140. {
  141. if (bits)
  142. {
  143. WAVEFORMATEXTENSIBLE *waveFormat = (WAVEFORMATEXTENSIBLE *) mediaType->pbFormat;
  144. if (waveFormat->Format.cbSize >= 22)
  145. waveFormat->Samples.wValidBitsPerSample = bits;
  146. waveFormat->Format.wBitsPerSample = bits;
  147. waveFormat->Format.nBlockAlign = (waveFormat->Format.wBitsPerSample / 8) * waveFormat->Format.nChannels;
  148. waveFormat->Format.nAvgBytesPerSec = waveFormat->Format.nSamplesPerSec * waveFormat->Format.nBlockAlign;
  149. if (FAILED(formatProperties->SetMediaType(mediaType)))
  150. {
  151. // blah, just use the default settings then
  152. delete[] mediaType;
  153. mediaType = NewMediaType(formatProperties);
  154. }
  155. }
  156. AudioFormat::Open(mediaType);
  157. delete[] mediaType;
  158. audioOutputNum = output;
  159. reader->SetOutputProps(audioOutputNum, formatProperties);
  160. reader->GetStreamNumberForOutput(audioOutputNum, &streamNum);
  161. formatProperties->Release();
  162. reader->SetReadStreamSamples(streamNum, FALSE);
  163. IWMHeaderInfo *headerInfo = 0;
  164. reader->QueryInterface(&headerInfo);
  165. WMT_ATTR_DATATYPE type = WMT_TYPE_QWORD;
  166. WORD byteLength = sizeof(QWORD);
  167. WORD blah = 0;
  168. headerInfo->GetAttributeByName(&blah, g_wszWMDuration, &type, (BYTE *)&length, &byteLength);
  169. headerInfo->Release();
  170. return true;
  171. }
  172. delete[] mediaType;
  173. formatProperties->Release();
  174. }
  175. }
  176. return false;
  177. }
  178. extern "C"
  179. __declspec(dllexport) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
  180. {
  181. ExtendedReadStruct *read = new ExtendedReadStruct;
  182. if (read->Open(fn)
  183. && read->FindOutput(*bps, *nch))
  184. {
  185. *nch = read->Channels();
  186. *bps = read->BitSize();
  187. *srate = read->SampleRate();
  188. __int64 bytespersec = ((*nch) * (*bps / 8) * (*srate));
  189. __int64 s = (bytespersec * ((__int64)read->length)) / (__int64)(1000 * 10000);
  190. *size = (int)s;
  191. return reinterpret_cast<intptr_t>(read);
  192. }
  193. else
  194. {
  195. delete read;
  196. return 0;
  197. }
  198. }
  199. extern "C"
  200. __declspec(dllexport) intptr_t winampGetExtendedRead_getData(intptr_t handle, char *dest, int len, int *killswitch)
  201. {
  202. ExtendedReadStruct *read = reinterpret_cast<ExtendedReadStruct *>(handle);
  203. return read->ReadAudio(dest, len);
  204. }
  205. extern "C"
  206. __declspec(dllexport) void winampGetExtendedRead_close(intptr_t handle)
  207. {
  208. ExtendedReadStruct *read = reinterpret_cast<ExtendedReadStruct *>(handle);
  209. delete read;
  210. }