aboutsummaryrefslogtreecommitdiff
path: root/Src/mp3-mpg123/mp3_in_mp4.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/mp3-mpg123/mp3_in_mp4.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/mp3-mpg123/mp3_in_mp4.cpp')
-rw-r--r--Src/mp3-mpg123/mp3_in_mp4.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/Src/mp3-mpg123/mp3_in_mp4.cpp b/Src/mp3-mpg123/mp3_in_mp4.cpp
new file mode 100644
index 00000000..f4437e7a
--- /dev/null
+++ b/Src/mp3-mpg123/mp3_in_mp4.cpp
@@ -0,0 +1,228 @@
+// used to decode an MPEG-1 audio object in an MPEG-4 ISO Media file
+#include "mp3_in_mp4.h"
+#include "api__mp3-mpg123.h"
+#include "../nsutil/pcm.h"
+
+// {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F}
+static const GUID playbackConfigGroupGUID =
+{ 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf } };
+
+#define FHG_DELAY 529
+MPEG4_MP3::MPEG4_MP3()
+{
+ channels = 0;
+ gain = 1;
+ floatingPoint = false;
+ decoder = 0;
+ sample_rate = 0;
+ bits = 16;
+ pregap = FHG_DELAY;
+}
+
+MPEG4_MP3::~MPEG4_MP3()
+{
+ if (decoder) {
+ mpg123_delete(decoder);
+ decoder = 0;
+ }
+}
+
+int MPEG4_MP3::OpenEx(size_t _bits, size_t _maxChannels, bool useFloat)
+{
+ _bits = bits;
+ floatingPoint = useFloat;
+ if (floatingPoint)
+ bits = 32;
+ else
+ bits = (int)_bits;
+
+ decoder = mpg123_new(NULL, NULL);
+ long flags = MPG123_QUIET|MPG123_FORCE_FLOAT|MPG123_SKIP_ID3V2|MPG123_IGNORE_STREAMLENGTH|MPG123_IGNORE_INFOFRAME;
+ if (_maxChannels == 1) {
+ flags |= MPG123_FORCE_MONO;
+ }
+ mpg123_param(decoder, MPG123_FLAGS, flags, 0);
+ mpg123_param(decoder, MPG123_RVA, MPG123_RVA_OFF, 0);
+ mpg123_open_feed(decoder);
+ return MP4_SUCCESS;
+}
+
+const char *MPEG4_MP3::GetCodecInfoString()
+{
+ return 0;
+}
+
+int MPEG4_MP3::CanHandleCodec(const char *codecName)
+{
+ if (!lstrcmpA(codecName, "mp4a"))
+ return 1;
+ else
+ return 0;
+}
+
+int MPEG4_MP3::CanHandleType(unsigned __int8 type)
+{
+ switch(type)
+ {
+ case MP4_MPEG4_LAYER3_AUDIO:
+ case MP4_MPEG4_LAYER2_AUDIO:
+ case MP4_MPEG4_LAYER1_AUDIO:
+ case MP4_TYPE_MPEG1_AUDIO:
+ case MP4_TYPE_MPEG2_AUDIO:
+ //case MP4_TYPE_MPEG4_AUDIO:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int MPEG4_MP3::DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
+{
+ if (!decoder)
+ return MP4_FAILURE;
+
+ *outputBufferBytes = 0;
+ mpg123_feed(decoder, (unsigned char *)inputBuffer, inputBufferBytes);
+
+ for (;;) {
+ // get the decoded data out
+ size_t pcm_buf_used=0;
+ float decodeBuf[1152*2];
+ int err = mpg123_read(decoder, (unsigned char *)decodeBuf, sizeof(decodeBuf), &pcm_buf_used);
+
+ if (pcm_buf_used) {
+ if (!_UpdateProperties()) {
+ return MP4_FAILURE;
+ }
+ // deal with pregap
+ int numSamples = (int)pcm_buf_used / sizeof(float);
+ int offset = min(numSamples, pregap * channels);
+ numSamples -= offset;
+ pregap -= offset / channels;
+ float *pcm_buf = decodeBuf + offset;
+
+ // convert to destination sample format
+
+ nsutil_pcm_FloatToInt_Interleaved(outputBuffer, pcm_buf, bits, numSamples);
+
+ *outputBufferBytes += numSamples * bits / 8;
+ outputBuffer = (char *)outputBuffer + numSamples * bits / 8;
+
+ return MP4_SUCCESS;
+ } else if (err == MPG123_NEED_MORE) {
+ *outputBufferBytes = 0;
+ return MP4_NEED_MORE_INPUT;
+ } else if (err == MPG123_NEW_FORMAT) {
+ continue;
+ } else if (err == MPG123_OK) {
+ continue;
+ }
+ else
+ return MP4_FAILURE;
+ }
+ return MP4_SUCCESS;
+}
+
+bool MPEG4_MP3::_UpdateProperties()
+{
+ if (decoder && (!channels || !sample_rate)) {
+ long sample_rate = 44100;
+ int channels = 2;
+ int encoding = 0;
+ if (mpg123_getformat(decoder, &sample_rate, &channels, &encoding) == MPG123_OK) {
+ this->channels = channels;
+ this->sample_rate = sample_rate;
+ }
+ }
+
+ return channels && sample_rate;
+}
+int MPEG4_MP3::GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
+{
+ if (_UpdateProperties()) {
+ *sampleRate = this->sample_rate;
+ *channels = this->channels;
+ *bitsPerSample = bits;
+ *isFloat = floatingPoint;
+ return MP4_SUCCESS;
+ } else {
+ return MP4_FAILURE;
+ }
+}
+
+int MPEG4_MP3::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample)
+{
+ bool dummy;
+ return GetOutputPropertiesEx(sampleRate, channels, bitsPerSample, &dummy);
+}
+
+void MPEG4_MP3::Close()
+{
+ if (decoder) {
+ mpg123_delete(decoder);
+ decoder = 0;
+ }
+}
+
+void MPEG4_MP3::Flush()
+{
+ mpg123_open_feed(decoder);
+ pregap = FHG_DELAY;
+}
+
+int MPEG4_MP3::SetGain(float _gain)
+{
+ gain = _gain;
+ return MP4_SUCCESS;
+}
+
+int MPEG4_MP3::GetCurrentBitrate(unsigned int *bitrate)
+{
+ mpg123_frameinfo frameInfo;
+ if (mpg123_info(decoder, &frameInfo) == MPG123_OK) {
+ *bitrate = frameInfo.bitrate;
+ return MP4_SUCCESS;
+ } else {
+ return MP4_FAILURE;
+ }
+}
+
+int MPEG4_MP3::OutputFrameSize(size_t *frameSize)
+{
+ if (_UpdateProperties()) {
+ *frameSize = (bits/8) * channels * mpg123_spf(decoder);
+ return MP4_SUCCESS;
+ } else {
+ return MP4_FAILURE;
+ }
+}
+
+int MPEG4_MP3::CanHandleMPEG4Type(unsigned __int8 type)
+{
+ switch (type)
+ {
+ case MP4_MPEG4_LAYER1_AUDIO:
+ case MP4_MPEG4_LAYER2_AUDIO:
+ case MP4_MPEG4_LAYER3_AUDIO:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+#define CBCLASS MPEG4_MP3
+START_DISPATCH;
+CB(MPEG4_AUDIO_OPEN_EX, OpenEx)
+CB(MPEG4_AUDIO_CODEC_INFO_STRING, GetCodecInfoString)
+CB(MPEG4_AUDIO_BITRATE, GetCurrentBitrate)
+CB(MPEG4_AUDIO_FRAMESIZE, OutputFrameSize)
+CB(MPEG4_AUDIO_OUTPUTINFO, GetOutputProperties)
+CB(MPEG4_AUDIO_OUTPUTINFO_EX, GetOutputPropertiesEx)
+CB(MPEG4_AUDIO_DECODE, DecodeSample)
+VCB(MPEG4_AUDIO_FLUSH, Flush)
+VCB(MPEG4_AUDIO_CLOSE, Close)
+CB(MPEG4_AUDIO_HANDLES_CODEC, CanHandleCodec)
+CB(MPEG4_AUDIO_HANDLES_TYPE, CanHandleType)
+CB(MPEG4_AUDIO_HANDLES_MPEG4_TYPE, CanHandleMPEG4Type)
+CB(MPEG4_AUDIO_SET_GAIN, SetGain)
+END_DISPATCH;