diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/mp3-mpg123/mp3_in_mp4.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-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.cpp | 228 |
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; |