aboutsummaryrefslogtreecommitdiff
path: root/Src/aacdec/NSVAACDecoder.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/aacdec/NSVAACDecoder.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/aacdec/NSVAACDecoder.cpp')
-rw-r--r--Src/aacdec/NSVAACDecoder.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/Src/aacdec/NSVAACDecoder.cpp b/Src/aacdec/NSVAACDecoder.cpp
new file mode 100644
index 00000000..94a6efd7
--- /dev/null
+++ b/Src/aacdec/NSVAACDecoder.cpp
@@ -0,0 +1,229 @@
+#include "NSVAACDecoder.h"
+
+#include <assert.h>
+#include "api.h"
+#include "../nsv/nsvlib.h"
+#include "api.h"
+#include "../nsv/nsvlib.h"
+#include "../nsv/dec_if.h"
+#include <string.h>
+#include <bfc/platform/export.h>
+#include "NSVAACDecoder.h"
+#include <bfc/error.h>
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+NSVAACDecoder *NSVAACDecoder::CreateDecoder()
+{
+ CAccessUnitPtr access_unit = CAccessUnit_Create(0, 0);
+ if (!access_unit)
+ return 0;
+
+ NSVAACDecoder *decoder=0;
+ WASABI_API_MEMMGR->New(&decoder);
+ if (!decoder)
+ {
+ CAccessUnit_Destroy(&access_unit);
+ return 0;
+ }
+ decoder->Initialize(access_unit);
+ return decoder;
+}
+
+NSVAACDecoder::NSVAACDecoder()
+{
+ access_unit = 0;
+ composition_unit = 0;
+ decoder = 0;
+ source_position=0;
+ out_left=0;
+ in_position=0;
+}
+
+NSVAACDecoder::~NSVAACDecoder()
+{
+ mp4AudioDecoder_Destroy(&decoder);
+ CAccessUnit_Destroy(&access_unit);
+ CCompositionUnit_Destroy(&composition_unit);
+}
+
+void NSVAACDecoder::Initialize(CAccessUnitPtr _access_unit)
+{
+ access_unit = _access_unit;
+}
+
+void NSVAACDecoder::flush()
+{
+ if (decoder)
+ mp4AudioDecoder_Reset(decoder, MP4AUDIODECPARAM_DEFAULT, 0);
+}
+
+
+static void ConfigureADTS(CSAudioSpecificConfig* asc, nsaac_adts_header_t header)
+{
+ asc->m_aot = (AUDIO_OBJECT_TYPE)(header->profile + 1);
+ asc->m_channelConfiguration = header->channel_configuration;
+ asc->m_channels = nsaac_adts_get_channel_count(header);
+ asc->m_nrOfStreams = 1;
+ asc->m_samplesPerFrame = 1024;
+ asc->m_samplingFrequencyIndex = header->sample_rate_index;
+ asc->m_samplingFrequency = nsaac_adts_get_samplerate(header);
+ asc->m_avgBitRate = 0; /* only needed for tvq */
+ asc->m_mpsPresentFlag = -1;
+ asc->m_saocPresentFlag = -1;
+ asc->m_ldmpsPresentFlag = -1;
+}
+
+// returns -1 on error, 0 on success (done with data in 'in'), 1 on success
+// but to pass 'in' again next time around.
+int NSVAACDecoder::decode(void *in, int in_len, void *out, int *out_len, unsigned int out_fmt[8])
+{
+ if (out_left)
+ {
+ unsigned int channels;
+ unsigned int sample_rate;
+ if (CCompositionUnit_GetChannels(composition_unit, &channels) != MP4AUDIODEC_OK
+ || CCompositionUnit_GetSamplingRate(composition_unit, &sample_rate) != MP4AUDIODEC_OK)
+ return -1;
+
+
+ out_fmt[0] = NSV_MAKETYPE('P', 'C', 'M', ' ');
+ out_fmt[1] = sample_rate;
+ out_fmt[2] = channels;
+ out_fmt[3] = 16;
+
+ const uint8_t *audio_output=0;
+ CCompositionUnit_GetPcmPtr(composition_unit, &audio_output);
+ size_t copy_size = min(out_left, *out_len);
+ memcpy(out, audio_output + source_position, copy_size);
+ *out_len = copy_size;
+ out_left -= copy_size;
+ source_position += copy_size;
+ return 1;
+;
+ }
+
+ in = (uint8_t *)in + in_position;
+ in_len -= in_position;
+
+ if (in_len > 7)
+ {
+ ADTSHeader header;
+ if (nsaac_adts_parse(&header, (const uint8_t *)in) == NErr_Success)
+ {
+ if (!decoder)
+ {
+ CSAudioSpecificConfig asc;
+ memset(&asc, 0, sizeof(asc));
+ ConfigureADTS(&asc, &header);
+
+ CSAudioSpecificConfig *asc_array = &asc;
+ decoder = mp4AudioDecoder_Create(&asc_array, 1);
+ if (decoder)
+ {
+ mp4AudioDecoder_SetParam(decoder, TDL_MODE, SWITCH_ON);
+ mp4AudioDecoder_SetParam(decoder, CONCEALMENT_ENERGYINTERPOLATION, SWITCH_OFF);
+ composition_unit = CCompositionUnit_Create(max(asc.m_channels, 8), asc.m_samplesPerFrame * 2, asc.m_samplingFrequency, 6144, CUBUFFER_PCMTYPE_INT16);
+ }
+ if (!decoder || !composition_unit)
+ {
+ in_position=0;
+ return -1;
+ }
+ }
+ if (header.frame_length > in_len)
+ {
+ in_position=0;
+ return -1;
+ }
+ if (header.frame_length != in_len)
+ {
+ in_position+=header.frame_length;
+ }
+ else
+ {
+ in_position=0;
+ }
+
+ CAccessUnit_Reset(access_unit);
+ CAccessUnit_Assign(access_unit, (const uint8_t *)in + 7, header.frame_length-7);
+ CCompositionUnit_Reset(composition_unit);
+ MP4_RESULT result = mp4AudioDecoder_DecodeFrame(decoder, &access_unit, composition_unit);
+
+ if (result == MP4AUDIODEC_OK)
+ {
+ unsigned int channels;
+ unsigned int samples_per_channel;
+ unsigned int sample_rate;
+ if (CCompositionUnit_GetSamplesPerChannel(composition_unit, &samples_per_channel) != MP4AUDIODEC_OK
+ || CCompositionUnit_GetChannels(composition_unit, &channels) != MP4AUDIODEC_OK
+ || CCompositionUnit_GetSamplingRate(composition_unit, &sample_rate) != MP4AUDIODEC_OK)
+ return -1;
+
+ size_t num_samples = samples_per_channel * channels;
+ size_t output_size = num_samples * 2 /* 16 bits */;
+
+ const uint16_t *audio_output=0;
+ CCompositionUnit_GetPcmPtr(composition_unit, &audio_output);
+ size_t copy_size = min(output_size, *out_len);
+ memcpy(out, audio_output, copy_size);
+ *out_len = copy_size;
+ out_left = output_size - copy_size;
+ source_position = copy_size;
+
+ out_fmt[0] = NSV_MAKETYPE('P', 'C', 'M', ' ');
+ out_fmt[1] = sample_rate;
+ out_fmt[2] = channels;
+ out_fmt[3] = 16;
+
+ int br;
+ CCompositionUnit_GetProperty(composition_unit, CUBUFFER_AVGBITRATE, &br);
+ out_fmt[4] =br/1000;
+ if (in_position)
+ return 1;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+ }
+ else
+ {
+ in_position=0;
+ return -1;
+ }
+ }
+ *out_len = 0;
+ in_position=0;
+ return 0;
+
+}
+
+
+
+IAudioDecoder *NSVDecoder::CreateAudioDecoder(FOURCC format, IAudioOutput **output)
+{
+ switch (format)
+ {
+ case NSV_MAKETYPE('A', 'A', 'C', ' ') :
+ case NSV_MAKETYPE('A', 'A', 'C', 'P'):
+ case NSV_MAKETYPE('A', 'P', 'L', ' '):
+ {
+ NSVAACDecoder *dec = NSVAACDecoder::CreateDecoder();
+ return dec;
+ }
+
+ default:
+ return 0;
+ }
+}
+
+
+#define CBCLASS NSVDecoder
+START_DISPATCH;
+CB(SVC_NSVFACTORY_CREATEAUDIODECODER, CreateAudioDecoder)
+END_DISPATCH;
+#undef CBCLASS