Декодирование звука libavcodec создает образцы мусораC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Декодирование звука libavcodec создает образцы мусора

Сообщение Anonymous »

Я пытаюсь написать функцию, которая извлекает необработанные данные сэмпла из аудиофайлов. Но при отладке тестового файла я обнаружил, что выборки в плоском формате с плавающей запятой не находились в диапазоне от -1,0f до 1,0f, как указано в документации.
Вот функция:

Код: Выделить всё

AudioResource::ReturnCode AudioResource::LoadFromFile(std::string FilePath)
{
std::string FileURL = "file:" + FilePath;
AVFormatContext* FormatContext = nullptr;
int Error = avformat_open_input(&FormatContext, FileURL.c_str(), nullptr, nullptr);

if (Error < 0)
{
return ERROR_OPENING_FILE;
}

Error = avformat_find_stream_info(FormatContext, nullptr);
if (Error < 0)
{
return ERROR_FINDING_STREAM_INFO;
}

int AudioStream = -1;
AVCodecParameters* CodecParams;
for (int i = 0; i < FormatContext->nb_streams; i++)
{
if (FormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
CodecParams = FormatContext->streams[i]->codecpar;
AudioStream = i;
}
}

if (AudioStream == -1)
{
return ERROR_AUDIO_STREAM_NOT_FOUND;
}

SampleRate = FormatContext->streams[AudioStream]->codecpar->sample_rate;
AVSampleFormat SampleFormat = (AVSampleFormat) FormatContext->streams[AudioStream]->codecpar->format;
Channels = FormatContext->streams[AudioStream]->codecpar->ch_layout.nb_channels;

if (Channels >  2)
{
return ERROR_UNSUPPORTED_CHANNEL_COUNT;
}

switch (SampleFormat)
{
case AV_SAMPLE_FMT_NONE:
return ERROR_UNKWON_SAMPLE_FORMAT;
break;
case AV_SAMPLE_FMT_U8:
BytesPerSample = 1;
if (Channels == 1)
{
SampleType == MONO_8BIT;
}
else
{
SampleType = STEREO_8BIT;
}
break;
case AV_SAMPLE_FMT_S16:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_S32:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType= STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_FLT:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_DBL:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_U8P:
BytesPerSample = 1;
if (Channels == 1)
{
SampleType = MONO_8BIT;
}
else
{
SampleType = STEREO_8BIT;
}
break;
case AV_SAMPLE_FMT_S16P:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_S32P:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_FLTP:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_DBLP:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_S64:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
case AV_SAMPLE_FMT_S64P:
BytesPerSample = 2;
if (Channels == 1)
{
SampleType = MONO_16BIT;
}
else
{
SampleType = STEREO_16BIT;
}
break;
default:
return ERROR_UNKWON_SAMPLE_FORMAT;
break;
}

const AVCodec* AudioCodec = avcodec_find_decoder(CodecParams->codec_id);
AVCodecContext* CodecContext = avcodec_alloc_context3(AudioCodec);
avcodec_parameters_to_context(CodecContext, CodecParams);
avcodec_open2(CodecContext, AudioCodec, nullptr);

AVPacket* CurrentPacket = av_packet_alloc();
AVFrame* CurrentFrame = av_frame_alloc();

while (av_read_frame(FormatContext, CurrentPacket) >= 0)
{
avcodec_send_packet(CodecContext, CurrentPacket);
for (;;)
{
Error = avcodec_receive_frame(CodecContext,  CurrentFrame);
if ((Error == AVERROR(EAGAIN)) || (Error == AVERROR_EOF))
{
break;
}
else if (Error == AVERROR(EINVAL))
{
return ERROR_RECIVING_FRAME;
}
else if (Error != 0)
{
return ERROR_UNEXSPECTED;
}

if (SampleFormat == AV_SAMPLE_FMT_U8)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_S16)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_S32)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_FLT)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_DBL)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_U8P)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_S16P)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_S32P)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_FLTP) //
{
if (Channels == 2)
{
for (size_t i = 0; i < CurrentFrame->linesize[0]; i += sizeof(float))
{
float CurrentLeftSample = 0.0f;
float CurrentRightSample = 0.0f;
memcpy(&CurrentLeftSample, &CurrentFrame->data[0][i], sizeof(float));
memcpy(&CurrentRightSample, &CurrentFrame->data[1][i], sizeof(float));

short int QuantizedLeftSample = roundf(CurrentLeftSample * 0x7fff);
short int QuantizedRightSample = roundf(CurrentRightSample * 0x7fff);

LoadByteData(QuantizedLeftSample, AudioData);
LoadByteData(QuantizedRightSample, AudioData);
}
}
else
{

}
}
else if (SampleFormat == AV_SAMPLE_FMT_DBLP)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_S64)
{

}
else if (SampleFormat == AV_SAMPLE_FMT_S64P)
{

}
else
{
return ERROR_UNEXSPECTED;
}
}
}

av_frame_free(&CurrentFrame);
av_packet_free(&CurrentPacket);
avcodec_free_context(&CodecContext);
avformat_free_context(FormatContext);
return OK;
}
Здесь я читаю из буфера AVFrame

Код: Выделить всё

for (size_t i = 0; i < CurrentFrame->linesize[0]; i += sizeof(float))
{
float CurrentLeftSample = 0.0f;
float CurrentRightSample = 0.0f;
memcpy(&CurrentLeftSample, &CurrentFrame->data[0][i], sizeof(float));
memcpy(&CurrentRightSample, &CurrentFrame->data[1][i], sizeof(float));

short int QuantizedLeftSample = roundf(CurrentLeftSample * 0x7fff);
short int QuantizedRightSample = roundf(CurrentRightSample * 0x7fff);

LoadByteData(QuantizedLeftSample, AudioData);
LoadByteData(QuantizedRightSample, AudioData);
}
Я пробовал использовать различные параметры, такие как CurrentFrame->nb_samples, CurrentFrame->buf[0].size, в цикле for, но безуспешно, он все равно создает те же результаты.
Будем очень благодарны за любую помощь.

Подробнее здесь: https://stackoverflow.com/questions/791 ... ld-samples
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»