Skip to content

Commit

Permalink
setRawData in M4A enabled
Browse files Browse the repository at this point in the history
If an esda Atom is available in m4a headers, the default values (AAC-LC, stereo, 44100Hz) do not need to be set. Now also 'AAC Scalable Sample Rate', 'AAC Long Term Prediction' and 'AAC Spectral Band Replication' are also possible
  • Loading branch information
schreibfaul1 committed Aug 13, 2024
1 parent 01388f6 commit 6b0d555
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 16 deletions.
18 changes: 14 additions & 4 deletions src/Audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Created on: Oct 26.2018
*
* Version 3.0.12g
* Version 3.0.12h
* Updated on: Aug 09.2024
* Author: Wolle (schreibfaul1)
*
Expand Down Expand Up @@ -414,6 +414,9 @@ void Audio::setDefaults() {
m_ID3Size = 0;
m_haveNewFilePos = 0;
m_validSamples = 0;
m_M4A_chConfig = 0;
m_M4A_objectType = 0;
m_M4A_sampleRate = 0;
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -2141,6 +2144,7 @@ int Audio::read_M4A_Header(uint8_t* data, size_t len) {
else if(objectType == 5) { AUDIO_INFO("AudioObjectType: AAC Spectral Band Replication"); }
else if(objectType == 6) { AUDIO_INFO("AudioObjectType: AAC Scalable"); }
else { AUDIO_INFO("unknown ObjectType %x, stop", objectType); stopSong();}
if(objectType < 7) m_M4A_objectType = objectType;

const uint32_t samplingFrequencies[13] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350};
uint8_t sRate = (ASC & 0x0600) >> 7; // next 4 bits Sampling Frequencies
Expand All @@ -2151,6 +2155,7 @@ int Audio::read_M4A_Header(uint8_t* data, size_t len) {
if(chConfig == 1) AUDIO_INFO("Channel Configurations: front-center");
if(chConfig == 2) AUDIO_INFO("Channel Configurations: front-left, front-right");
if(chConfig > 2) { log_e("Channel Configurations with more than 2 channels is not allowed, stop!"); stopSong();}
if(chConfig < 3) m_M4A_chConfig = chConfig;

uint8_t frameLengthFlag = (ASC & 0x04);
uint8_t dependsOnCoreCoder = (ASC & 0x02);
Expand All @@ -2168,7 +2173,9 @@ int Audio::read_M4A_Header(uint8_t* data, size_t len) {
int srate = bigEndian(data + offset + 26, 4); //
setBitsPerSample(bps);
setChannels(channel);
if(!m_M4A_chConfig) m_M4A_chConfig = channel;
setSampleRate(srate);
m_M4A_sampleRate = srate;
setBitrate(bps * channel * srate);
AUDIO_INFO("ch; %i, bps: %i, sr: %i", channel, bps, srate);
if(audioDataPos && getDatamode() == AUDIO_LOCALFILE) {
Expand Down Expand Up @@ -3168,7 +3175,7 @@ void Audio::processLocalFile() {
if(!(audiofile && m_f_running && getDatamode() == AUDIO_LOCALFILE)) return; // guard

static uint32_t ctime = 0;
const uint32_t timeout = 2500; // ms
const uint32_t timeout = 6500; // ms
const uint32_t maxFrameSize = InBuff.getMaxBlockSize(); // every mp3/aac frame is not bigger
static bool f_fileDataComplete;
static uint32_t byteCounter; // count received data
Expand Down Expand Up @@ -4426,7 +4433,10 @@ int Audio::findNextSync(uint8_t* data, size_t len) {
}
if(m_codec == CODEC_AAC) { nextSync = AACFindSyncWord(data, len); }
if(m_codec == CODEC_M4A) {
AACSetRawBlockParams(0, 2, 44100, 1);
if(!m_M4A_chConfig)m_M4A_chConfig = 2; // guard
if(!m_M4A_sampleRate)m_M4A_sampleRate = 44100;
if(!m_M4A_objectType)m_M4A_objectType = 2;
AACSetRawBlockParams(m_M4A_chConfig, m_M4A_sampleRate, m_M4A_objectType);
m_f_playing = true;
nextSync = 0;
}
Expand Down Expand Up @@ -4779,7 +4789,7 @@ void Audio::printDecodeError(int r) {
}
AUDIO_INFO("MP3 decode error %d : %s", r, e);
}
if(m_codec == CODEC_AAC) {
if(m_codec == CODEC_AAC || m_codec == CODEC_M4A) {
e = AACGetErrorMessage(abs(r));
AUDIO_INFO("AAC decode error %d : %s", r, e);
}
Expand Down
5 changes: 4 additions & 1 deletion src/Audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Created on: Oct 28,2018
*
* Version 3.0.12f
* Version 3.0.12h
* Updated on: Jul 29.2024
* Author: Wolle (schreibfaul1)
*/
Expand Down Expand Up @@ -534,6 +534,9 @@ class Audio : private AudioBuffer{
uint8_t m_vuLeft = 0; // average value of samples, left channel
uint8_t m_vuRight = 0; // average value of samples, right channel
uint8_t m_audioTaskCoreId = 0;
uint8_t m_M4A_objectType = 0; // set in read_M4A_Header
uint8_t m_M4A_chConfig = 0; // set in read_M4A_Header
uint16_t m_M4A_sampleRate = 0; // set in read_M4A_Header
int16_t* m_outBuff = NULL; // Interleaved L/R
int16_t m_validSamples = {0}; // #144
int16_t m_curSample{0};
Expand Down
40 changes: 32 additions & 8 deletions src/aac_decoder/aac_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* aac_decoder.cpp
* faad2 - ESP32 adaptation
* Created on: 12.09.2023
* Updated on: 28.07.2024
* Updated on: 13.08.2024
*/


Expand All @@ -20,11 +20,14 @@ NeAACDecFrameInfo_t frameInfo;
NeAACDecConfigurationPtr_t conf;
bool f_decoderIsInit = false;
bool f_firstCall = false;
bool f_setRaWBlockParams = false;
uint32_t aacSamplerate = 0;
uint8_t aacChannels = 0;
uint8_t aacProfile = 0;
static uint16_t validSamples = 0;
clock_t before;
float compressionRatio = 1;
mp4AudioSpecificConfig_t* mp4ASC;

//----------------------------------------------------------------------------------------------------------------------
bool AACDecoder_IsInit(){
Expand All @@ -35,9 +38,10 @@ bool AACDecoder_AllocateBuffers(){
before = clock();
hAac = NeAACDecOpen();
conf = NeAACDecGetCurrentConfiguration(hAac);
NeAACDecSetConfiguration(hAac, conf);

if(hAac) f_decoderIsInit = true;
f_firstCall = false;
f_setRaWBlockParams = false;
return f_decoderIsInit;
}
//----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -75,11 +79,11 @@ int AACFindSyncWord(uint8_t *buf, int nBytes){
return 0;
}
//----------------------------------------------------------------------------------------------------------------------
int AACSetRawBlockParams(int copyLast, int nChans, int sampRateCore, int profile){
(void)copyLast;
(void)nChans;
(void)sampRateCore;
(void)profile;
int AACSetRawBlockParams(int nChans, int sampRateCore, int profile){
f_setRaWBlockParams = true;
aacChannels = nChans; // 1: Mono, 2: Stereo
aacSamplerate = sampRateCore; // 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
aacProfile = profile; //1: AAC Main, 2: AAC LC (Low Complexity), 3: AAC SSR (Scalable Sample Rate), 4: AAC LTP (Long Term Prediction)
return 0;
}
//----------------------------------------------------------------------------------------------------------------------
Expand All @@ -104,10 +108,30 @@ int AACGetBitsPerSample(){
return 16;
}
//----------------------------------------------------------------------------------------------------------------------
void createAudioSpecificConfig(uint8_t* config, uint8_t audioObjectType, uint8_t samplingFrequencyIndex, uint8_t channelConfiguration) {
config[0] = (audioObjectType << 3) | (samplingFrequencyIndex >> 1);
config[1] = (samplingFrequencyIndex << 7) | (channelConfiguration << 3);
}
//----------------------------------------------------------------------------------------------------------------------
int AACDecode(uint8_t *inbuf, int32_t *bytesLeft, short *outbuf){
uint8_t* ob = (uint8_t*)outbuf;
if (f_firstCall == false){
int8_t err = NeAACDecInit(hAac, inbuf, *bytesLeft, &aacSamplerate, &aacChannels);
if(f_setRaWBlockParams){ // set raw AAC values, e.g. for M4A config.
f_setRaWBlockParams = false;
conf->defSampleRate = aacSamplerate;
conf->outputFormat = FAAD_FMT_16BIT;
conf->useOldADTSFormat = 1;
conf->defObjectType = 2;
int8_t ret = NeAACDecSetConfiguration(hAac, conf);

uint8_t specificInfo[2];
createAudioSpecificConfig(specificInfo, aacProfile, get_sr_index(aacSamplerate), aacChannels);
int8_t err = NeAACDecInit2(hAac, specificInfo, 2, &aacSamplerate, &aacChannels);
}
else{
NeAACDecSetConfiguration(hAac, conf);
int8_t err = NeAACDecInit(hAac, inbuf, *bytesLeft, &aacSamplerate, &aacChannels);
}
f_firstCall = true;
}

Expand Down
11 changes: 9 additions & 2 deletions src/aac_decoder/aac_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@
* aac_decoder.h
* faad2 - ESP32 adaptation
* Created on: 12.09.2023
* Updated on: 28.07.2024
* Updated on: 13.08.2024
*/


#pragma once

#include <stdint.h>
#pragma GCC diagnostic warning "-Wunused-function"

struct AudioSpecificConfig {
uint8_t audioObjectType;
uint8_t samplingFrequencyIndex;
uint8_t channelConfiguration;
};

bool AACDecoder_IsInit();
bool AACDecoder_AllocateBuffers();
void AACDecoder_FreeBuffers();
uint8_t AACGetFormat();
uint8_t AACGetParametricStereo();
uint8_t AACGetSBR();
int AACFindSyncWord(uint8_t *buf, int nBytes);
int AACSetRawBlockParams(int copyLast, int nChans, int sampRateCore, int profile);
int AACSetRawBlockParams(int nChans, int sampRateCore, int profile);
int16_t AACGetOutputSamps();
int AACGetBitrate();
int AACGetChannels();
Expand Down
3 changes: 2 additions & 1 deletion src/aac_decoder/libfaad/neaacdec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5127,7 +5127,8 @@ int8_t AudioSpecificConfigFrombitfile(bitfile_t* ld, program_config_t* pce, uint
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int8_t AudioSpecificConfig2(uint8_t* pBuffer, uint32_t buffer_size, program_config_t* pce, uint8_t short_form) {
uint8_t ret = 0;
bitfile_t ld = {0,0,0,0,0,0,0,0,0}; // ld.bits_left = 0;
bitfile_t ld;
memset(&ld, 0, sizeof(ld));
faad_initbits(&ld, pBuffer, buffer_size);
faad_byte_align(&ld);
ret = AudioSpecificConfigFrombitfile(&ld, pce, buffer_size, short_form);
Expand Down

0 comments on commit 6b0d555

Please sign in to comment.