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