ExtendedRead.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #include "main.h"
  2. #include "adts.h"
  3. #include <memory.h>
  4. #include <malloc.h>
  5. #include <xutility>
  6. #include <assert.h>
  7. #include <shlwapi.h>
  8. #include <foundation/error.h>
  9. #include "../nu/RingBuffer.h"
  10. #include <api/service/waservicefactory.h>
  11. // {19450308-90D7-4E45-8A9D-DC71E67123E2}
  12. static const GUID adts_aac_guid =
  13. { 0x19450308, 0x90d7, 0x4e45, { 0x8a, 0x9d, 0xdc, 0x71, 0xe6, 0x71, 0x23, 0xe2 } };
  14. // {4192FE3F-E843-445c-8D62-51BE5EE5E68C}
  15. static const GUID adts_mp2_guid =
  16. { 0x4192fe3f, 0xe843, 0x445c, { 0x8d, 0x62, 0x51, 0xbe, 0x5e, 0xe5, 0xe6, 0x8c } };
  17. class GapCutter
  18. {
  19. public:
  20. GapCutter() {}
  21. void SetEndSize( int postSize );
  22. void SetSize( int preSize, int postSize );
  23. void Flush( int time_in_ms );
  24. int Write( void *dest, void *input, size_t inputBytes );
  25. private:
  26. RingBuffer ringBuffer;
  27. int preCut = 0;
  28. int preCutSize = 0;
  29. };
  30. void GapCutter::SetEndSize(int postSize)
  31. {
  32. if (postSize < 0)
  33. postSize = 0;
  34. if (postSize)
  35. {
  36. ringBuffer.Reset();
  37. ringBuffer.reserve(postSize);
  38. }
  39. }
  40. void GapCutter::SetSize( int preSize, int postSize )
  41. {
  42. if ( preSize < 0 )
  43. preSize = 0;
  44. if ( postSize < 0 )
  45. postSize = 0;
  46. SetEndSize( postSize );
  47. preCutSize = preSize;
  48. preCut = preSize;
  49. }
  50. void GapCutter::Flush( int time_in_ms )
  51. {
  52. // if (time_in_ms == 0) // TODO: calculate actual delay if we seek within the encoder delay area
  53. preCut = preCutSize; // reset precut size if we seek to the start
  54. ringBuffer.clear();
  55. }
  56. int GapCutter::Write( void *dest, void *input, size_t inputBytes ) // returns # of bytes written
  57. {
  58. int bytesWritten = 0;
  59. unsigned __int8 *in = (unsigned __int8 *)input;
  60. unsigned __int8 *out = (unsigned __int8 *)dest;
  61. // cut pre samples, if necessary
  62. intptr_t pre = min( preCut, (intptr_t)inputBytes );
  63. in += pre;
  64. inputBytes -= pre;
  65. preCut -= (int)pre;
  66. if ( !inputBytes )
  67. return bytesWritten;
  68. size_t remainingFill = ringBuffer.avail();
  69. intptr_t fillWrite = min( (intptr_t)( inputBytes - remainingFill ), (intptr_t)ringBuffer.size() ); // only write fill buffer if we've got enough left to fill it up
  70. if ( fillWrite > 0 )
  71. {
  72. size_t written = ringBuffer.read( out, fillWrite );
  73. bytesWritten += (int)written;
  74. out += written;
  75. }
  76. remainingFill = ringBuffer.avail();
  77. int outWrite = (int)max( 0, (intptr_t)( inputBytes - remainingFill ) );
  78. if ( outWrite )
  79. memcpy( out, in, outWrite );
  80. bytesWritten += outWrite;
  81. in += outWrite;
  82. inputBytes -= outWrite;
  83. if ( inputBytes )
  84. ringBuffer.write( in, inputBytes );
  85. return bytesWritten;
  86. }
  87. struct ExtendedRead
  88. {
  89. ExtendedRead() { memset(&data, 0, sizeof(data)); }
  90. ~ExtendedRead()
  91. {
  92. file.Close();
  93. if ( decoder )
  94. {
  95. decoder->Close();
  96. decoder->Release();
  97. }
  98. }
  99. bool Open( const wchar_t *fn, int *size, int *bps, int *nch, int *srate, bool useFloat );
  100. adts *decoder = NULL;
  101. int bits = 0;
  102. size_t initialData = 0;
  103. int frameSize = 0;
  104. GapCutter cutter;
  105. CGioFile file;
  106. #define DATA_SIZE (6*4*2*2*1152)
  107. unsigned char data[DATA_SIZE];
  108. };
  109. bool ExtendedRead::Open(const wchar_t *fn, int *size, int *bps, int *nch, int *srate, bool useFloat)
  110. {
  111. if (file.Open(fn, config_max_bufsize_k) != NErr_Success)
  112. return false;
  113. int downmix = 0;
  114. bool allowsurround = 1;
  115. if (*nch == 1)
  116. {
  117. downmix = 1;
  118. allowsurround = 0;
  119. }
  120. else if (*nch == 2)
  121. {
  122. allowsurround = 0;
  123. }
  124. if (useFloat)
  125. bits=32;
  126. else if (*bps == 24)
  127. bits = 24;
  128. else
  129. {
  130. bits = 16;
  131. *bps = 16;
  132. }
  133. wchar_t *ext = PathFindExtensionW(fn);
  134. if (!_wcsicmp(ext, L".vlb"))
  135. {
  136. return false;
  137. }
  138. else if (!_wcsicmp(ext, L".aac") || !_wcsicmp(ext, L".apl"))
  139. {
  140. waServiceFactory *factory = mod.service->service_getServiceByGuid(adts_aac_guid);
  141. if (factory)
  142. decoder = (adts *)factory->getInterface();
  143. }
  144. else
  145. {
  146. waServiceFactory *factory = mod.service->service_getServiceByGuid(adts_mp2_guid);
  147. if (factory)
  148. decoder = (adts *)factory->getInterface();
  149. }
  150. if (!decoder)
  151. return false;
  152. decoder->Initialize(!!downmix, 0, allowsurround, bits, false, useFloat);
  153. decoder->Open(&file);
  154. size_t bitrate;
  155. bool done=false;
  156. while (!done)
  157. {
  158. switch (decoder->Sync(&file, data, sizeof(data), &initialData, &bitrate))
  159. {
  160. case adts::SUCCESS:
  161. done=true;
  162. break;
  163. case adts::FAILURE:
  164. case adts::ENDOFFILE:
  165. return false;
  166. case adts::NEEDMOREDATA:
  167. break;
  168. }
  169. }
  170. size_t numBits = 0;
  171. decoder->GetOutputParameters(&numBits, nch, srate);
  172. *bps = bits = (int)numBits;
  173. frameSize = bits / 8 * *nch;
  174. if (config_gapless)
  175. cutter.SetSize((file.prepad + (int)decoder->GetDecoderDelay())*frameSize, (file.postpad - (int)decoder->GetDecoderDelay())*frameSize);
  176. if (file.m_vbr_samples) // exact number of samples in the LAME header, how nice :)
  177. *size = (int)file.m_vbr_samples*frameSize;
  178. else if (file.m_vbr_ms) // if we know the milliseconds accurately
  179. *size = MulDiv(*srate * frameSize, file.m_vbr_ms, 1000); // our size should be mostly accurate
  180. else // no helpful info to go on
  181. {
  182. // just guess based on bitrate and content length
  183. bitrate=decoder->GetCurrentBitrate();
  184. int len_ms = MulDiv(file.GetContentLength(), 8, (int)bitrate);
  185. *size = MulDiv(*srate * frameSize, len_ms, 1000);
  186. }
  187. return true;
  188. }
  189. extern "C"
  190. {
  191. //returns handle!=0 if successful, 0 if error
  192. //size will return the final nb of bytes written to the output, -1 if unknown
  193. __declspec(dllexport) intptr_t winampGetExtendedRead_openW(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
  194. {
  195. ExtendedRead *ext = new ExtendedRead;
  196. if (ext)
  197. {
  198. if (ext->Open(fn, size, bps, nch, srate, false))
  199. return reinterpret_cast<intptr_t>(ext);
  200. delete ext;
  201. }
  202. return 0;
  203. }
  204. __declspec(dllexport) intptr_t winampGetExtendedRead_openW_float(const wchar_t *fn, int *size, int *bps, int *nch, int *srate)
  205. {
  206. ExtendedRead *ext = new ExtendedRead;
  207. if (ext)
  208. {
  209. if (ext->Open(fn, size, bps, nch, srate, true))
  210. return reinterpret_cast<intptr_t>(ext);
  211. delete ext;
  212. }
  213. return 0;
  214. }
  215. //returns nb of bytes read. -1 if read error (like CD ejected). if (ret==0), EOF is assumed
  216. __declspec(dllexport) size_t winampGetExtendedRead_getData(intptr_t handle, char *dest, size_t len, int *killswitch)
  217. {
  218. ExtendedRead *ext = (ExtendedRead *)handle;
  219. int copied = 0;
  220. if (ext)
  221. {
  222. len -= (len % ext->frameSize); // only do whole frames
  223. while (len)
  224. {
  225. size_t toMove = min(len, ext->initialData);
  226. int toCopy = ext->cutter.Write(dest, ext->data, toMove);
  227. if (ext->initialData != toMove)
  228. memmove(ext->data, ext->data + toMove, ext->initialData - toMove);
  229. ext->initialData -= toMove;
  230. len -= toCopy;
  231. copied += toCopy;
  232. dest += toCopy;
  233. if (!ext->initialData)
  234. {
  235. size_t written = 0, bitrate, endCut = 0;
  236. int ret = ext->decoder->Decode(&ext->file, ext->data, DATA_SIZE, &written, &bitrate, &endCut);
  237. if (config_gapless && endCut)
  238. ext->cutter.SetEndSize((int)(endCut - ext->decoder->GetDecoderDelay())*ext->frameSize);
  239. ext->initialData = written;
  240. if (/*ret != adts::SUCCESS && */!ext->initialData && (copied || ret == adts::ENDOFFILE))
  241. return copied;
  242. if (ret == adts::FAILURE)
  243. return -1;
  244. }
  245. }
  246. }
  247. return copied;
  248. }
  249. // return nonzero on success, zero on failure.
  250. __declspec(dllexport) int winampGetExtendedRead_setTime(intptr_t handle, int millisecs)
  251. {
  252. ExtendedRead *ext = (ExtendedRead *)handle;
  253. if (ext)
  254. {
  255. if (!ext->file.IsSeekable()) return 0; // not seekable
  256. int br = ext->file.GetAvgVBRBitrate();
  257. if (!br) br = (int)ext->decoder->GetCurrentBitrate();
  258. if (!br) return 0; // can't find a valid bitrate
  259. ext->cutter.Flush(millisecs); // fucko?
  260. ext->decoder->Flush(&ext->file);
  261. ext->file.Seek(millisecs,br);
  262. return 1;
  263. }
  264. return 0;
  265. }
  266. __declspec(dllexport) void winampGetExtendedRead_close(intptr_t handle)
  267. {
  268. ExtendedRead *ext = (ExtendedRead *)handle;
  269. if (ext) delete ext;
  270. }
  271. }