TUTORIAL 2 – ADVANCED AUDIO CODING
In this tutorial, you leverage existing libraries like FFmpeg or fdk-aac to implement an AAC
encoder in C. Below is an example of how you can use the fdk-aac library to encode raw
PCM audio data into AAC format.
Prerequisites:
1. Install the fdk-aac library:
a. On Ubuntu: sudo apt-get install libfdk-aac-dev
b. On macOS: brew install fdk-aac
2. Link the library when compiling your program.
Example C Program Using fdk-aac:
#include <stdio.h>
#include <stdlib.h>
#include <fdk-aac/aacenc_lib.h>
#define PCM_BUFFER_SIZE 1024
#define AAC_BUFFER_SIZE 2048
int main() {
// Initialize AAC encoder
HANDLE_AACENCODER hAacEncoder;
if (aacEncOpen(&hAacEncoder, 0, 2) != AACENC_OK) {
fprintf(stderr, "Unable to open AAC encoder\n");
return 1;
}
// Set encoder parameters
if (aacEncoder_SetParam(hAacEncoder, AACENC_AOT, AOT_AAC_LC) != AACENC_OK ||
aacEncoder_SetParam(hAacEncoder, AACENC_SAMPLERATE, 44100) != AACENC_OK ||
aacEncoder_SetParam(hAacEncoder, AACENC_CHANNELMODE, MODE_2) !=
AACENC_OK ||
aacEncoder_SetParam(hAacEncoder, AACENC_BITRATE, 128000) != AACENC_OK) {
fprintf(stderr, "Unable to set AAC encoder parameters\n");
aacEncClose(&hAacEncoder);
return 1;
}
// Initialize encoder
if (aacEncEncode(hAacEncoder, NULL, NULL, NULL, NULL) != AACENC_OK) {
fprintf(stderr, "Unable to initialize AAC encoder\n");
aacEncClose(&hAacEncoder);
return 1;
}
// Open input PCM file
FILE *pcmFile = fopen("input.pcm", "rb");
if (!pcmFile) {
fprintf(stderr, "Unable to open input PCM file\n");
aacEncClose(&hAacEncoder);
return 1;
}
// Open output AAC file
FILE *aacFile = fopen("output.aac", "wb");
if (!aacFile) {
fprintf(stderr, "Unable to open output AAC file\n");
fclose(pcmFile);
aacEncClose(&hAacEncoder);
return 1;
}
// Buffers for PCM and AAC data
short pcmBuffer[PCM_BUFFER_SIZE];
unsigned char aacBuffer[AAC_BUFFER_SIZE];
// Encoding loop
while (1) {
// Read PCM data
size_t pcmRead = fread(pcmBuffer, sizeof(short), PCM_BUFFER_SIZE, pcmFile);
if (pcmRead == 0) {
break; // End of file
}
// Encode PCM to AAC
AACENC_BufDesc inBufDesc = {0}, outBufDesc = {0};
AACENC_InArgs inArgs = {0};
AACENC_OutArgs outArgs = {0};
void *inBuffer[] = {pcmBuffer};
int inBufferIds[] = {IN_AUDIO_DATA};
int inBufferSize[] = {pcmRead * sizeof(short)};
int inBufferElSize[] = {sizeof(short)};
inBufDesc.numBufs = 1;
inBufDesc.bufs = inBuffer;
inBufDesc.bufferIdentifiers = inBufferIds;
inBufDesc.bufSizes = inBufferSize;
inBufDesc.bufElSizes = inBufferElSize;
void *outBuffer[] = {aacBuffer};
int outBufferIds[] = {OUT_BITSTREAM_DATA};
int outBufferSize[] = {AAC_BUFFER_SIZE};
int outBufferElSize[] = {1};
outBufDesc.numBufs = 1;
outBufDesc.bufs = outBuffer;
outBufDesc.bufferIdentifiers = outBufferIds;
outBufDesc.bufSizes = outBufferSize;
outBufDesc.bufElSizes = outBufferElSize;
inArgs.numInSamples = pcmRead;
if (aacEncEncode(hAacEncoder, &inBufDesc, &outBufDesc, &inArgs, &outArgs) !=
AACENC_OK) {
fprintf(stderr, "Encoding failed\n");
break;
}
// Write AAC data to file
if (outArgs.numOutBytes > 0) {
fwrite(aacBuffer, 1, outArgs.numOutBytes, aacFile);
}
}
// Clean up
fclose(pcmFile);
fclose(aacFile);
aacEncClose(&hAacEncoder);
printf("AAC encoding completed successfully.\n");
return 0;
}
Explanation:
1. Initialization:
a. The aacEncOpen function initializes the AAC encoder.
b. Parameters like sample rate, bitrate, and channel mode are set using
aacEncoder_SetParam.
2. Encoding:
a. PCM data is read from a file (input.pcm) and passed to the encoder.
b. The encoded AAC data is written to an output file (output.aac).
3. Cleanup:
a. Files and the encoder are closed after encoding is complete.
Compilation:
To compile the program, use the following command:
gcc -o aac_encoder aac_encoder.c -lfdk-aac
Input and Output:
• Provide a raw PCM file (input.pcm) as input. The file should contain 16-bit signed
PCM data at 44.1 kHz sample rate with 2 channels (stereo).
• The output will be an AAC file (output.aac).
Notes:
• This example uses the fdk-aac library, which is a high-quality AAC encoder.
• Ensure the input PCM file matches the sample rate and channel configuration
specified in the code.
• For more advanced features (e.g., multi-channel encoding, different AAC profiles),
refer to the fdk-aac documentation.