LAMEInfo.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #include "LAMEInfo.h"
  2. #include "MPEGHeader.h"
  3. #include "foundation/error.h"
  4. #include <string.h>
  5. #include "nu/ByteReader.h"
  6. #include "nu/BitReader.h"
  7. // Xing header -
  8. // 4 Xing
  9. // 4 flags
  10. // 4 frames
  11. // 4 bytes
  12. // 100 toc
  13. // 4 bytes VBR quality
  14. // Lame tag
  15. // 9 bytes - release name
  16. // 11
  17. // Lame extended info tag
  18. // http://gabriel.mp3-tech.org/mp3infotag.html
  19. LAMEInfo::LAMEInfo()
  20. {
  21. memset(this, 0, sizeof(LAMEInfo));
  22. }
  23. bool LAMEInfo::Flag(int flag) const
  24. {
  25. return flags & flag;
  26. }
  27. int LAMEInfo::GetGaps(size_t *pregap, size_t *postgap)
  28. {
  29. if (!encoder_delay)
  30. return NErr_Empty;
  31. *pregap = encoder_delay;
  32. *postgap = padding;
  33. return NErr_Success;
  34. }
  35. uint64_t LAMEInfo::GetSeekPoint(double percent) const
  36. {
  37. // interpolate in TOC to get file seek point in bytes
  38. int a;
  39. uint64_t seekpoint;
  40. double fa, fb, fx;
  41. percent*=100.0;
  42. if (percent < 0.0)
  43. percent = 0.0;
  44. if (percent > 100.0)
  45. percent = 100.0;
  46. a = (int)(percent);
  47. if (a > 99) a = 99;
  48. fa = toc[a];
  49. if (a < 99)
  50. {
  51. fb = toc[a + 1];
  52. }
  53. else
  54. {
  55. fb = 256.0;
  56. }
  57. fx = fa + (fb - fa) * (percent - a);
  58. seekpoint = (uint64_t) ((1.0 / 256.0) * fx * bytes);
  59. return seekpoint;
  60. }
  61. uint64_t LAMEInfo::GetSamples() const
  62. {
  63. if (flags&FRAMES_FLAG)
  64. {
  65. uint64_t samples = frames * samples_per_frame;
  66. samples -= (encoder_delay + padding);
  67. return samples;
  68. }
  69. return 0;
  70. }
  71. uint32_t LAMEInfo::GetFrames() const
  72. {
  73. if (flags&FRAMES_FLAG)
  74. return frames;
  75. else
  76. return 0;
  77. }
  78. double LAMEInfo::GetLengthSeconds() const
  79. {
  80. if (flags&FRAMES_FLAG)
  81. {
  82. return (double)GetSamples() / (double)sample_rate;
  83. }
  84. return 0;
  85. }
  86. int LAMEInfo::Read(const MPEGHeader &frame, const uint8_t *buffer, size_t buffer_length)
  87. {
  88. int flags;
  89. bool crc_hack_applied=false;
  90. bytereader_value_t byte_reader;
  91. /* maybe toolame writes these things also, I dunno. we'll just abort for now */
  92. if (frame.layer != MPEGHeader::Layer3)
  93. return 0;
  94. bytereader_init(&byte_reader, buffer, buffer_length);
  95. sample_rate = frame.GetSampleRate();
  96. version = frame.mpeg_version;
  97. samples_per_frame = frame.GetSamplesPerFrame();
  98. // skip sideinfo
  99. if (frame.mpeg_version == MPEGHeader::MPEG1) // MPEG 1
  100. {
  101. if (frame.channel_mode == MPEGHeader::Mono)
  102. bytereader_advance(&byte_reader, 17);
  103. else
  104. bytereader_advance(&byte_reader, 32);
  105. }
  106. else if (frame.mpeg_version == MPEGHeader::MPEG2) // MPEG 2
  107. {
  108. if (frame.channel_mode == MPEGHeader::Mono)
  109. bytereader_advance(&byte_reader, 9);
  110. else
  111. bytereader_advance(&byte_reader, 17);
  112. }
  113. else if (frame.mpeg_version == MPEGHeader::MPEG2_5) // MPEG 2
  114. {
  115. if (frame.channel_mode == MPEGHeader::Mono)
  116. bytereader_advance(&byte_reader, 9);
  117. else
  118. bytereader_advance(&byte_reader, 17);
  119. }
  120. if (bytereader_size(&byte_reader) > buffer_length /* check for wraparound */
  121. || bytereader_size(&byte_reader) < 8)
  122. return NErr_Insufficient;
  123. again:
  124. if (bytereader_show_u32_be(&byte_reader) == 'Info')
  125. cbr=1;
  126. else if (bytereader_show_u32_be(&byte_reader) != 'Xing' && bytereader_show_u32_be(&byte_reader) != 'Lame')
  127. {
  128. // if there's CRC data, LAME sometimes writes to the wrong position
  129. if (frame.IsCRC() && !crc_hack_applied)
  130. {
  131. crc_hack_applied=true;
  132. bytereader_advance(&byte_reader, 2);
  133. goto again;
  134. }
  135. return NErr_False;
  136. }
  137. bytereader_advance(&byte_reader, 4); // skip Xing tag
  138. flags = this->flags = bytereader_read_u32_be(&byte_reader);
  139. if (flags & FRAMES_FLAG)
  140. {
  141. if (bytereader_size(&byte_reader) < 4)
  142. return NErr_Insufficient;
  143. frames = bytereader_read_u32_be(&byte_reader);
  144. }
  145. if (flags & BYTES_FLAG)
  146. {
  147. if (bytereader_size(&byte_reader) < 4)
  148. return NErr_Insufficient;
  149. bytes = bytereader_read_u32_be(&byte_reader);
  150. }
  151. if (flags & TOC_FLAG)
  152. {
  153. if (bytereader_size(&byte_reader) < 100)
  154. return NErr_Insufficient;
  155. int i;
  156. memcpy(toc, bytereader_pointer(&byte_reader), 100);
  157. // verify that TOC isn't empty
  158. for (i = 0; i < 100; i++)
  159. if (toc[i]) break;
  160. if (i == 100)
  161. flags &= ~TOC_FLAG;
  162. bytereader_advance(&byte_reader, 100);
  163. }
  164. vbr_scale = -1;
  165. if (flags & VBR_SCALE_FLAG)
  166. {
  167. if (bytereader_size(&byte_reader) < 4)
  168. return NErr_Insufficient;
  169. vbr_scale = bytereader_read_u32_be(&byte_reader);
  170. }
  171. if (bytereader_size(&byte_reader) < 27)
  172. return NErr_Success; // stop here if we have to, we have at least some data
  173. if (bytereader_show_u32_be(&byte_reader) == 'LAME')
  174. {
  175. for (int i=0;i<9;i++)
  176. encoder[i]=bytereader_read_u8(&byte_reader);
  177. encoder[9]=0; // null terminate in case tag used all 9 characters
  178. if (bytereader_show_u8(&byte_reader) == '(')
  179. {
  180. // read 11 more characters
  181. for (int i=9;i<20;i++)
  182. encoder[i]=bytereader_read_u8(&byte_reader);
  183. encoder[20]=0;
  184. }
  185. else
  186. {
  187. tag_revision = bytereader_show_u8(&byte_reader)>>4;
  188. if (tag_revision == 0)
  189. {
  190. encoding_method = bytereader_read_u8(&byte_reader)&0xF; // VBR method
  191. lowpass = bytereader_read_u8(&byte_reader)*100; // lowpass value
  192. peak=bytereader_read_f32_be(&byte_reader); // read peak value
  193. // read track gain
  194. int16_t gain_word = bytereader_read_s16_be(&byte_reader);
  195. if ((gain_word & 0xFC00) == 0x2C00)
  196. {
  197. replaygain_track_gain = (float)(gain_word & 0x01FF);
  198. replaygain_track_gain /= 10;
  199. if (gain_word & 0x0200)
  200. replaygain_track_gain = -replaygain_track_gain;
  201. }
  202. // read album gain
  203. gain_word = bytereader_read_s16_be(&byte_reader);
  204. if ((gain_word & 0xFC00) == 0x4C00)
  205. {
  206. replaygain_album_gain = (float)(gain_word & 0x01FF);
  207. replaygain_album_gain /= 10;
  208. if (gain_word & 0x0200)
  209. replaygain_album_gain = -replaygain_album_gain;
  210. }
  211. bytereader_advance(&byte_reader, 1); // skip encoding flags + ATH type
  212. abr_bitrate = bytereader_read_u8(&byte_reader); // bitrate
  213. // get the encoder delay and padding, annoyingly as 12 bit values packed into 3 bytes
  214. BitReader bit_reader;
  215. bit_reader.data = (const uint8_t *)bytereader_pointer(&byte_reader);
  216. bit_reader.numBits = 24;
  217. const uint8_t *temp = (const uint8_t *)bytereader_pointer(&byte_reader);
  218. encoder_delay = bit_reader.getbits(12);
  219. padding = bit_reader.getbits(12);
  220. bytereader_advance(&byte_reader, 3);
  221. bytereader_advance(&byte_reader, 4);
  222. // skip misc
  223. // skip MP3Gain reconstruction info
  224. // skip surround info and preset info
  225. music_length = bytereader_read_u32_be(&byte_reader);
  226. music_crc = bytereader_read_u16_be(&byte_reader);
  227. tag_crc = bytereader_read_u16_be(&byte_reader);
  228. }
  229. }
  230. }
  231. else if (!memcmp(bytereader_pointer(&byte_reader), "iTunes", 6))
  232. {
  233. int i=0;
  234. while (bytereader_size(&byte_reader) && i < 31)
  235. {
  236. encoder[i] = bytereader_read_u8(&byte_reader);
  237. if (!encoder[i])
  238. break;
  239. i++;
  240. }
  241. encoder[31]=0;
  242. }
  243. else if (!memcmp(bytereader_pointer(&byte_reader), "\0\0\0\0mp3HD", 9))
  244. {
  245. bytereader_advance(&byte_reader, 4);
  246. for (int i=0;i<5;i++)
  247. encoder[i] = bytereader_read_u8(&byte_reader);
  248. encoder[5]=0;
  249. }
  250. return NErr_Success;
  251. }