134 lines
2.5 KiB
C
134 lines
2.5 KiB
C
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <3ds.h>
|
|
|
|
#include "error.h"
|
|
#include "m4a.h"
|
|
#include "playback.h"
|
|
|
|
/* TODO: Integrate proper AAC decoder library (libfaad2, fdk-aac, or minimp4) */
|
|
/* For now, this is a stub implementation */
|
|
|
|
static size_t* buffSize;
|
|
static uint32_t rate = 44100;
|
|
static uint8_t channels = 2;
|
|
|
|
static int initM4a(const char* file);
|
|
static uint32_t rateM4a(void);
|
|
static uint8_t channelM4a(void);
|
|
static uint64_t decodeM4a(void* buffer);
|
|
static void exitM4a(void);
|
|
static size_t getFileSamplesM4a(void);
|
|
|
|
/**
|
|
* Set decoder parameters for M4A/AAC.
|
|
*
|
|
* \param decoder Structure to store parameters.
|
|
*/
|
|
void setM4a(struct decoder_fn* decoder)
|
|
{
|
|
decoder->init = &initM4a;
|
|
decoder->rate = &rateM4a;
|
|
decoder->channels = &channelM4a;
|
|
buffSize = &(decoder->buffSize);
|
|
decoder->decode = &decodeM4a;
|
|
decoder->exit = &exitM4a;
|
|
decoder->getFileSamples = &getFileSamplesM4a;
|
|
}
|
|
|
|
/**
|
|
* Check if a file is an M4A/AAC/ALAC file.
|
|
*
|
|
* \param file File location.
|
|
* \return 0 on success, -1 on failure.
|
|
*/
|
|
int isM4a(const char* file)
|
|
{
|
|
FILE* ftest = fopen(file, "rb");
|
|
uint32_t fileSig;
|
|
uint32_t ftypSig;
|
|
|
|
if(ftest == NULL)
|
|
return -1;
|
|
|
|
/* Read first 4 bytes (should be size of ftyp atom) */
|
|
if(fread(&fileSig, 4, 1, ftest) == 0)
|
|
{
|
|
fclose(ftest);
|
|
return -1;
|
|
}
|
|
|
|
/* Read next 4 bytes (should be 'ftyp') */
|
|
if(fread(&ftypSig, 4, 1, ftest) == 0)
|
|
{
|
|
fclose(ftest);
|
|
return -1;
|
|
}
|
|
|
|
fclose(ftest);
|
|
|
|
/* Check for 'ftyp' signature (0x70797466 in little-endian) */
|
|
if(ftypSig == 0x70797466)
|
|
return 0;
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int initM4a(const char* file)
|
|
{
|
|
(void)file;
|
|
|
|
/* TODO: Initialize AAC decoder */
|
|
/* This requires:
|
|
* 1. Parse MP4 container to find AAC audio track
|
|
* 2. Extract decoder config (sample rate, channels, etc.)
|
|
* 3. Initialize AAC decoder with config
|
|
*/
|
|
|
|
/* Set default values for now */
|
|
rate = 44100;
|
|
channels = 2;
|
|
*buffSize = rate * channels * sizeof(int16_t);
|
|
|
|
errno = FILE_NOT_SUPPORTED;
|
|
return -1;
|
|
}
|
|
|
|
static uint32_t rateM4a(void)
|
|
{
|
|
return rate;
|
|
}
|
|
|
|
static uint8_t channelM4a(void)
|
|
{
|
|
return channels;
|
|
}
|
|
|
|
static uint64_t decodeM4a(void* buffer)
|
|
{
|
|
(void)buffer;
|
|
|
|
/* TODO: Decode AAC frame */
|
|
/* This requires:
|
|
* 1. Read next AAC frame from MP4 container
|
|
* 2. Decode AAC frame to PCM samples
|
|
* 3. Write PCM samples to buffer
|
|
* 4. Return number of samples decoded
|
|
*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void exitM4a(void)
|
|
{
|
|
/* TODO: Clean up AAC decoder */
|
|
}
|
|
|
|
static size_t getFileSamplesM4a(void)
|
|
{
|
|
/* TODO: Calculate total samples from MP4 metadata */
|
|
return 0;
|
|
}
|