PCM в AAC с FAAC, numberBytesWritten ›› 16 бит?


Следующая итерация моего вопроса:

Спасибо за ваш вклад, это помогло мне немного больше понять об утилите Frame и inputSamples. Я внес изменения в свой исходный код с новыми знаниями, которые вы мне дали. Но у меня все еще есть проблемы, поэтому я, возможно, не совсем понял, что вы имели в виду. Вот моя функция OpenFile, извините за название, но позже я рефакторинг; когда получится =)

//-----------------------------------------------------------------------------
/* 
This Function Open a File containing the Audio, Binary, Data.
*///___________________________________________________________________________
const short* OpenFile(const char* fileName, long& fileSize, WavFormat* wav)
{
// ouvre le fichier
ifstream file;
file.open((char*)fileName, ios::binary|ios::in);

if (file.good())
{
    // Read the WAV's Header
    wav = CheckWavHeader(file, wav);

    cout << "chunkID: " << wav->chunkID <<'\n';
    cout << "chunkSize: " << wav->chunkSize <<'\n';
    cout << "format: " << wav->format <<'\n';
    cout << "subChunk1ID: " << wav->subChunk1ID <<'\n';
    cout << "subChunk1Size: " << wav->subChunk1Size <<'\n';
    cout << "audioFormat: " << wav->audioFormat <<'\n'; // audioFormat == 1, alors PCM 16bits
    cout << "numChannels: " << wav->numChannels <<'\n';
    cout << "sampleRate: " << wav->sampleRate <<'\n';
    cout << "byteRate: " << wav->byteRate <<'\n';
    cout << "blockAlign: " << wav->blockAlign <<'\n';
    cout << "bitsPerSample: " << wav->bitsPerSample <<'\n';
    cout << "subChunk2ID: " << wav->subChunk2ID <<'\n';
    cout << "subChunk2Size: " << wav->subChunk2Size <<'\n';

    // Get the file’s size
    file.seekg(0L, ios::end);
    fileSize = ((long)file.tellg() - DATA_POS);

    file.seekg(DATA_POS, ios::beg); // back to the data.

    // Read the Data into the Buffer
    uint nbSamples = fileSize / sizeof(short);
    short* inputArray = new short[nbSamples];
    file.read((char*)inputArray, fileSize);

    // Close the file and return the Data
    file.close();
    return (const short*)inputArray;
}
else
{
    exit(-1);
}
}

Я открываю файл, проверяю его размер, создаю короткий буфер, читаю wav-данные в короткий буфер и, наконец, возвращаю его.

В основном пока прокомментировал декодер G711. Когда я запускаю приложение, faacEncOpen дает мне 2048 для inputSamples (это логично, поскольку у меня есть 2 канала в файле Wav для FRAME_LEN, равного 1024). Итак, если я правильно понял, 1 кадр == 2048 сэмплов для моего приложения. Поэтому для каждого кадра, который я вызываю faacEncEncode, я задаю tmpInputBuffer, который является буфером того же размера, что и inputSamples, по индексу inputBuffer[i * inputSamples].

//-----------------------------------------------------------------------------
/*
The Main entry Point of the Application
*///_____________________________________________________________________________
int main()
{
// Get the File's Data
WavFormat* wav = new WavFormat;
long fileSize;
const short* fileInput = OpenFile("audioTest.wav", fileSize, wav);

// G711 mu-Law Decoder
//MuLawDecoder* decoder = new MuLawDecoder();
//short* inputBuffer = decoder->MuLawDecode_shortArray((byte*)fileInput, (int)nbChunk);

short* inputBuffer = (short*)fileInput;

// Info for FAAC
ulong sampleRate = wav->sampleRate;
uint numChannels = wav->numChannels;
ulong inputSamples;
ulong maxOutputBytes;

// Ouvre l'Encodeur et assigne la Configuration.
faacEncHandle hEncoder = faacEncOpen(sampleRate, numChannels, &inputSamples, &maxOutputBytes);
faacEncConfigurationPtr faacConfig = faacEncGetCurrentConfiguration(hEncoder);

faacConfig->inputFormat = FAAC_INPUT_16BIT;
faacConfig->bitRate = 64000;

int result = faacEncSetConfiguration(hEncoder, faacConfig);

/*Input Buffer and Output Buffer*/
byte* outputBuffer = new byte[maxOutputBytes];
int nbBytesWritten = 0;
Sink* sink = new Sink();

uint nbFrame = fileSize / inputSamples;
int32_t* tmpInputBuffer = new int32_t[inputSamples];

for (uint i = 0; i < nbFrame; i++)
{   
    strncpy((char*)tmpInputBuffer, (const char*)&inputBuffer[i * inputSamples], inputSamples);

    nbBytesWritten = faacEncEncode(hEncoder, tmpInputBuffer, inputSamples, outputBuffer, maxOutputBytes);

    cout << 100.0 * (float)i / nbFrame << "%\t nbBytesWritten = " << nbBytesWritten << "\n";

    if (nbBytesWritten > 0)
    {
        sink->AddAACStream(outputBuffer, nbBytesWritten);
    }
}

sink->WriteToFile("output.aac");

// Close AAC Encoder
faacEncClose(hEncoder);

// Supprimer tous les pointeurs
delete sink;
//delete decoder;
delete[] fileInput;
//delete[] inputBuffer;
delete[] outputBuffer;
delete[] tmpInputBuffer;

system("pause");

return 0;
}

Когда выходные данные сбрасываются в файл .acc (как RAW AAC), я использую приложение mp4muxer.exe для создания файла .mp4 для прослушивания окончательно преобразованного звука. Но звук не очень...

Мне интересно, есть ли что-то, чего я не вижу или не понимаю, что я должен.

Заранее благодарим вас за ваш полезный вклад.


person manBear    schedule 13.03.2011    source источник


Ответы (2)


Каждый вызов faacEncEncode кодирует inputSamples выборки, а не только одну. Ваш основной цикл должен прочитать это количество сэмплов из файла WAV во входной буфер, затем вызвать faacEncEncode один раз для этого буфера и, наконец, записать выходной буфер в файл AAC.

person Mike Seymour    schedule 13.03.2011
comment
Что ты делаешь с strncpy? В любом случае нет необходимости копировать входные данные во временный буфер, и strncpy прекратит копирование, когда найдет байт с нулевым значением, поскольку он предназначен для использования со строками, а не с двоичными данными. Просто используйте &inputBuffer[i * inputSamples] в качестве входного аргумента для faacEncode. - person Mike Seymour; 14.03.2011

Возможно, я неправильно понял, что вы делаете (если это так, было бы полезно знать: (1) какую функцию OpenFile вы вызываете, и действительно ли она (несмотря на название) читается файл, а также его открытие? (2) Как настроен inputBuffer?) но:

faacEncEncode ожидает, что ему будут предоставлены сэмплы на весь кадр. Кадр — это количество семплов, которые вы передали обратно в inputSamples при вызове faacEncOpen. (Конечно, вы можете дать ему меньше целого кадра, если вы достигли конца ввода.)

Таким образом, вы получаете 460 и 539 байтов для каждого из двух кадров, а не 16 бит в каждом случае. И похоже, что ваши указатели входных данных на самом деле каждый раз смещаются только на одну выборку, поэтому вы передаете ему сильно перекрывающиеся кадры. (И неправильное их количество; nbChunk — это не то количество кадров, которое у вас есть.)

person Gareth McCaughan    schedule 13.03.2011