1+ #include " common.h"
2+ #include " common-m4a.h"
3+ extern " C" {
4+ #include < libavformat/avformat.h>
5+ #include < libavcodec/avcodec.h>
6+ #include < libswresample/swresample.h>
7+ }
8+
9+ #include < vector>
10+ #include < string>
11+
12+ bool read_m4a (const std::string &fname, std::vector<float > &pcmf32, std::vector<std::vector<float >> &pcmf32s,
13+ bool stereo) {
14+ avformat_network_init ();
15+
16+ AVFormatContext *formatContext = avformat_alloc_context ();
17+ if (avformat_open_input (&formatContext, fname.c_str (), nullptr , nullptr ) != 0 ) {
18+ fprintf (stderr, " Could not open file %s\n " , fname.c_str ());
19+ return false ;
20+ }
21+
22+ if (avformat_find_stream_info (formatContext, nullptr ) < 0 ) {
23+ fprintf (stderr, " Could not find stream information\n " );
24+ avformat_close_input (&formatContext);
25+ return false ;
26+ }
27+
28+ const AVCodec *codec = nullptr ;
29+ int streamIndex = av_find_best_stream (formatContext, AVMEDIA_TYPE_AUDIO, -1 , -1 , &codec, 0 );
30+ if (streamIndex < 0 ) {
31+ fprintf (stderr, " Could not find any audio stream in the file\n " );
32+ avformat_close_input (&formatContext);
33+ return false ;
34+ }
35+
36+ AVCodecContext *codecContext = avcodec_alloc_context3 (codec);
37+ avcodec_parameters_to_context (codecContext, formatContext->streams [streamIndex]->codecpar );
38+
39+ if (avcodec_open2 (codecContext, codec, nullptr ) < 0 ) {
40+ fprintf (stderr, " Could not open codec\n " );
41+ avcodec_free_context (&codecContext);
42+ avformat_close_input (&formatContext);
43+ return false ;
44+ }
45+
46+ // bool need_resample = (codecContext->sample_rate != COMMON_SAMPLE_RATE);
47+ SwrContext *swrCtx = nullptr ;
48+ swrCtx = swr_alloc_set_opts (nullptr ,
49+ stereo ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO,
50+ AV_SAMPLE_FMT_FLT,
51+ COMMON_SAMPLE_RATE,
52+ codecContext->channel_layout ,
53+ codecContext->sample_fmt ,
54+ codecContext->sample_rate ,
55+ 0 , nullptr );
56+ if (!swrCtx || swr_init (swrCtx) < 0 ) {
57+ fprintf (stderr, " Could not initialize the resampling context\n " );
58+ swr_free (&swrCtx);
59+ avcodec_free_context (&codecContext);
60+ avformat_close_input (&formatContext);
61+ return false ;
62+ }
63+
64+
65+ AVPacket packet;
66+ av_init_packet (&packet);
67+ packet.data = nullptr ;
68+ packet.size = 0 ;
69+
70+ AVFrame *frame = av_frame_alloc ();
71+
72+ while (av_read_frame (formatContext, &packet) >= 0 ) {
73+ if (packet.stream_index == streamIndex) {
74+ // decode
75+ int ret = avcodec_send_packet (codecContext, &packet);
76+ if (ret < 0 ) {
77+ fprintf (stderr, " Error sending packet for decoding\n " );
78+ break ;
79+ }
80+
81+ while (ret >= 0 ) {
82+ ret = avcodec_receive_frame (codecContext, frame);
83+ if (ret == AVERROR (EAGAIN) || ret == AVERROR_EOF) {
84+ break ;
85+ } else if (ret < 0 ) {
86+ fprintf (stderr, " Error during decoding\n " );
87+ break ;
88+ }
89+
90+ // Direct processing of decoded frames
91+ uint8_t *out_buf[2 ] = {nullptr , nullptr };
92+ int out_channels = stereo ? 2 : 1 ;
93+ int out_samples = av_rescale_rnd (swr_get_delay (swrCtx, codecContext->sample_rate ) + frame->nb_samples ,
94+ COMMON_SAMPLE_RATE, codecContext->sample_rate , AV_ROUND_UP);
95+ av_samples_alloc (out_buf, nullptr , out_channels, out_samples, AV_SAMPLE_FMT_FLT, 0 );
96+ swr_convert (swrCtx, out_buf, out_samples, (const uint8_t **) frame->data , frame->nb_samples );
97+
98+ int data_size = av_samples_get_buffer_size (nullptr , out_channels, out_samples, AV_SAMPLE_FMT_FLT, 0 );
99+ for (int i = 0 ; i < data_size / sizeof (float ); ++i) {
100+ pcmf32.push_back (((float *) out_buf[0 ])[i]);
101+ if (stereo && out_buf[1 ] != nullptr ) {
102+ pcmf32s[0 ].push_back (((float *) out_buf[0 ])[i]);
103+ pcmf32s[1 ].push_back (((float *) out_buf[1 ])[i]);
104+ }
105+ }
106+
107+ if (out_buf[0 ]) {
108+ av_freep (&out_buf[0 ]);
109+ }
110+ if (stereo && out_buf[1 ]) {
111+ av_freep (&out_buf[1 ]);
112+ }
113+
114+ av_frame_unref (frame);
115+ }
116+ av_packet_unref (&packet);
117+ }
118+ av_packet_unref (&packet);
119+ }
120+
121+ // Clean up
122+ av_frame_free (&frame);
123+ swr_free (&swrCtx);
124+ avcodec_free_context (&codecContext);
125+ avformat_close_input (&formatContext);
126+ avformat_network_deinit ();
127+
128+ return true ;
129+ }
0 commit comments