gpt4 book ai didi

audio - 使用 libavcodec 将 .m4a 转换为 PCM

转载 作者:行者123 更新时间:2023-12-02 21:10:58 44 4
gpt4 key购买 nike

我正在尝试将 .m4a 文件转换为原始 PCM 文件,以便可以在 Audacity 中播放它。

根据 AVCodecContext,它是一个使用示例格式 AV_SAMPLE_FMT_FLTP 的 44100 Hz 轨道,据我了解,当使用 avcodec_decode_audio4 解码时,我应该获得两个浮点值数组(每个 channel 一个)。

我不确定 AVCodecContext 的 bits_per_coded_sample = 16 的重要性

不幸的是,Audacity 播放结果时就好像我将原始轨道与一些白噪声混合在一起一样。

这是我所做的一些示例代码。请注意,我还添加了一个使用签名 16 位非交错数据 (sample_format = AC_SAMPLE_FMT_S16P) 的轨道的案例,Audacity 可以正常播放。

int AudioDecoder::decode(std::string path)
{
const char* input_filename=path.c_str();

av_register_all();

AVFormatContext* container=avformat_alloc_context();
if(avformat_open_input(&container,input_filename,NULL,NULL)<0){
printf("Could not open file");
}

if(avformat_find_stream_info(container, NULL)<0){
printf("Could not find file info");
}
av_dump_format(container,0,input_filename,false);

int stream_id=-1;
int i;
for(i=0;i<container->nb_streams;i++){
if(container->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){
stream_id=i;
break;
}
}
if(stream_id==-1){
printf("Could not find Audio Stream");
}

AVDictionary *metadata=container->metadata;
AVCodecContext *ctx=container->streams[stream_id]->codec;
AVCodec *codec=avcodec_find_decoder(ctx->codec_id);

if(codec==NULL){
printf("cannot find codec!");
}

if(avcodec_open2(ctx,codec,NULL)<0){
printf("Codec cannot be found");
}

AVSampleFormat sfmt = ctx->sample_fmt;

AVPacket packet;
av_init_packet(&packet);
AVFrame *frame = avcodec_alloc_frame();

int buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE+ FF_INPUT_BUFFER_PADDING_SIZE;;
uint8_t buffer[buffer_size];
packet.data=buffer;
packet.size =buffer_size;

FILE *outfile = fopen("test.raw", "wb");

int len;
int frameFinished=0;

while(av_read_frame(container,&packet) >= 0)
{
if(packet.stream_index==stream_id)
{
//printf("Audio Frame read \n");
int len=avcodec_decode_audio4(ctx, frame, &frameFinished, &packet);

if(frameFinished)
{
if (sfmt==AV_SAMPLE_FMT_S16P)
{ // Audacity: 16bit PCM little endian stereo
int16_t* ptr_l = (int16_t*)frame->extended_data[0];
int16_t* ptr_r = (int16_t*)frame->extended_data[1];
for (int i=0; i<frame->nb_samples; i++)
{
fwrite(ptr_l++, sizeof(int16_t), 1, outfile);
fwrite(ptr_r++, sizeof(int16_t), 1, outfile);
}
}
else if (sfmt==AV_SAMPLE_FMT_FLTP)
{ //Audacity: big endian 32bit stereo start offset 7 (but has noise)
float* ptr_l = (float*)frame->extended_data[0];
float* ptr_r = (float*)frame->extended_data[1];
for (int i=0; i<frame->nb_samples; i++)
{
fwrite(ptr_l++, sizeof(float), 1, outfile);
fwrite(ptr_r++, sizeof(float), 1, outfile);
}
}
}
}
}
fclose(outfile);
av_close_input_file(container);
return 0;

}

我希望我刚刚完成了一个幼稚的转换(大多数/不太重要的位问题),但目前我无法弄清楚。请注意,Audacity 只能导入 32 位或 64 位浮点(大端或小端)的 RAW float 据。

感谢您的见解。

最佳答案

我认为问题出在“nb_samples”中。这不完全是你需要的。最好尝试使用“linesize[0]”。

示例:

char* ptr_l = (char*)frame->extended_data[0];
char* ptr_r = (char*)frame->extended_data[1];
size_t size = sizeof(float);
for (int i=0; i<frame->linesize[0]; i+=size)
{
fwrite(ptr_l, size, 1, outfile);
fwrite(ptr_r, size, 1, outfile);
ptr_l += size;
ptr_r += size;
}

它用于“float”,并对“int16_t”重复相同的操作。但“size”将是“sizeof(int16_t)”

关于audio - 使用 libavcodec 将 .m4a 转换为 PCM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14376218/

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com