@@ -10,129 +10,134 @@ extern "C" {
1010
1111namespace audioanalyzer {
1212
13- const char * FFmpegException::getMessage () const noexcept {
14- return message;
15- }
16-
17- std::vector<AmplitudeData> analyzeAudio (const char *filename, FFmpegException *errorPtr) {
18- std::vector<AmplitudeData> amplitudeData;
19-
20- // Allocate memory for the AVFormatContext
21- AVFormatContext *formatContext = avformat_alloc_context ();
22- if (!formatContext) {
23- *errorPtr = FFmpegException (" Failed to allocate AVFormatContext" );
24- return amplitudeData;
25- }
26-
27- // Open the input file
28- if (avformat_open_input (&formatContext, filename, nullptr , nullptr ) != 0 ) {
29- avformat_free_context (formatContext);
30- *errorPtr = FFmpegException (" Failed to open input file" );
31- return amplitudeData;
32- }
33-
34- // Find stream information
35- if (avformat_find_stream_info (formatContext, nullptr ) < 0 ) {
36- avformat_close_input (&formatContext);
37- *errorPtr = FFmpegException (" Failed to find stream information" );
38- return amplitudeData;
39- }
40-
41- // Find the best audio stream
42- int audioStreamIndex = av_find_best_stream (formatContext, AVMEDIA_TYPE_AUDIO, -1 , -1 , nullptr , 0 );
43- if (audioStreamIndex < 0 ) {
44- avformat_close_input (&formatContext);
45- *errorPtr = FFmpegException (" Failed to find audio stream" );
46- return amplitudeData;
47- }
48-
49- // Get codec parameters and find the corresponding decoder
50- AVCodecParameters *codecParameters = formatContext->streams [audioStreamIndex]->codecpar ;
51- const AVCodec *codec = avcodec_find_decoder (codecParameters->codec_id );
52- if (!codec) {
53- avformat_close_input (&formatContext);
54- *errorPtr = FFmpegException (" Failed to find codec" );
55- return amplitudeData;
56- }
57-
58- // Allocate memory for the AVCodecContext
59- AVCodecContext *codecContext = avcodec_alloc_context3 (codec);
60- if (!codecContext) {
61- avformat_close_input (&formatContext);
62- *errorPtr = FFmpegException (" Failed to allocate AVCodecContext" );
63- return amplitudeData;
64- }
65-
66- // Set codec parameters
67- if (avcodec_parameters_to_context (codecContext, codecParameters) < 0 ) {
68- avformat_close_input (&formatContext);
69- avcodec_free_context (&codecContext);
70- *errorPtr = FFmpegException (" Failed to set codec parameters" );
71- return amplitudeData;
72- }
73-
74- // Open the codec
75- if (avcodec_open2 (codecContext, codec, nullptr ) < 0 ) {
76- avformat_close_input (&formatContext);
77- avcodec_free_context (&codecContext);
78- *errorPtr = FFmpegException (" Failed to open codec" );
79- return amplitudeData;
80- }
81-
82- // Allocate memory for AVPacket and AVFrame
83- AVPacket packet;
84- AVFrame *frame = av_frame_alloc ();
85-
86- // Initialize variables for audio analysis
87- int sampleRate = codecContext->sample_rate ;
88- double accumulatedAmplitude = 0.0 ;
89- long sampleCount = 0 ;
90-
91- // Read frames from the input file
92- while (av_read_frame (formatContext, &packet) >= 0 ) {
93- if (packet.stream_index == audioStreamIndex) {
94- // Send the packet to the codec
95- if (avcodec_send_packet (codecContext, &packet) < 0 ) {
96- break ;
97- }
98-
99- // Receive frames from the codec
100- while (avcodec_receive_frame (codecContext, frame) >= 0 ) {
101- double timestampInSeconds = frame->pts * av_q2d (formatContext->streams [audioStreamIndex]->time_base );
102-
103- // Calculate amplitude for each sample in the frame
104- for (int i = 0 ; i < frame->nb_samples ; i++) {
105- for (int ch = 0 ; ch < codecContext->channels ; ch++) {
106- accumulatedAmplitude += std::abs (frame->data [ch][i]);
107- sampleCount++;
108-
109- // Calculate amplitude per second and store the data
110- if (sampleCount >= sampleRate) {
111- double amplitudePerSecond = accumulatedAmplitude / sampleRate;
112-
113- AmplitudeData data{};
114- data.timeInSeconds = timestampInSeconds;
115- data.amplitude = amplitudePerSecond;
116-
117- amplitudeData.push_back (data);
13+ const char * FFmpegException::getMessage () const noexcept {
14+ return message;
15+ }
11816
119- accumulatedAmplitude = 0.0 ;
120- sampleCount = 0 ;
17+ std::vector<AmplitudeData> analyzeAudio (const char *filename, FFmpegException *errorPtr) {
18+ std::vector<AmplitudeData> amplitudeData;
19+
20+ // Allocate memory for the AVFormatContext
21+ AVFormatContext *formatContext = avformat_alloc_context ();
22+ if (!formatContext) {
23+ *errorPtr = FFmpegException (" Failed to allocate AVFormatContext" );
24+ return amplitudeData;
25+ }
26+
27+ // Open the input file
28+ if (avformat_open_input (&formatContext, filename, nullptr , nullptr ) != 0 ) {
29+ avformat_free_context (formatContext);
30+ *errorPtr = FFmpegException (" Failed to open input file" );
31+ return amplitudeData;
32+ }
33+
34+ // Find stream information
35+ if (avformat_find_stream_info (formatContext, nullptr ) < 0 ) {
36+ avformat_close_input (&formatContext);
37+ *errorPtr = FFmpegException (" Failed to find stream information" );
38+ return amplitudeData;
39+ }
40+
41+ // Find the best audio stream
42+ int audioStreamIndex = av_find_best_stream (formatContext, AVMEDIA_TYPE_AUDIO, -1 , -1 , nullptr , 0 );
43+ if (audioStreamIndex < 0 ) {
44+ avformat_close_input (&formatContext);
45+ *errorPtr = FFmpegException (" Failed to find audio stream" );
46+ return amplitudeData;
47+ }
48+
49+ // Get codec parameters and find the corresponding decoder
50+ AVCodecParameters *codecParameters = formatContext->streams [audioStreamIndex]->codecpar ;
51+ const AVCodec *codec = avcodec_find_decoder (codecParameters->codec_id );
52+ if (!codec) {
53+ avformat_close_input (&formatContext);
54+ *errorPtr = FFmpegException (" Failed to find codec" );
55+ return amplitudeData;
56+ }
57+
58+ // Allocate memory for the AVCodecContext
59+ AVCodecContext *codecContext = avcodec_alloc_context3 (codec);
60+ if (!codecContext) {
61+ avformat_close_input (&formatContext);
62+ *errorPtr = FFmpegException (" Failed to allocate AVCodecContext" );
63+ return amplitudeData;
64+ }
65+
66+ // Set codec parameters
67+ if (avcodec_parameters_to_context (codecContext, codecParameters) < 0 ) {
68+ avformat_close_input (&formatContext);
69+ avcodec_free_context (&codecContext);
70+ *errorPtr = FFmpegException (" Failed to set codec parameters" );
71+ return amplitudeData;
72+ }
73+
74+ // Open the codec
75+ if (avcodec_open2 (codecContext, codec, nullptr ) < 0 ) {
76+ avformat_close_input (&formatContext);
77+ avcodec_free_context (&codecContext);
78+ *errorPtr = FFmpegException (" Failed to open codec" );
79+ return amplitudeData;
80+ }
81+
82+ // Allocate memory for AVPacket and AVFrame
83+ AVPacket packet;
84+ AVFrame *frame = av_frame_alloc ();
85+
86+ // Initialize variables for audio analysis
87+ int sampleRate = codecContext->sample_rate ;
88+ double accumulatedAmplitude = 0.0 ;
89+ long sampleCount = 0 ;
90+
91+ // Read frames from the input file
92+ while (av_read_frame (formatContext, &packet) >= 0 ) {
93+ if (packet.stream_index == audioStreamIndex) {
94+ // Send the packet to the codec
95+ if (avcodec_send_packet (codecContext, &packet) < 0 ) {
96+ break ;
97+ }
98+
99+ // Receive frames from the codec
100+ while (avcodec_receive_frame (codecContext, frame) >= 0 ) {
101+ double timestampInSeconds = frame->pts * av_q2d (formatContext->streams [audioStreamIndex]->time_base );
102+
103+ // Calculate amplitude for each sample in the frame
104+ for (int i = 0 ; i < frame->nb_samples ; i++) {
105+ for (int ch = 0 ; ch < codecContext->ch_layout .nb_channels ; ch++) {
106+ if (frame->data [ch]) {
107+ // Check if the index is within bounds
108+ if (i < frame->linesize [ch]) {
109+ accumulatedAmplitude += frame->data [ch][i];
110+ sampleCount++;
111+
112+ // Calculate amplitude per second and store the data
113+ if (sampleCount >= sampleRate) {
114+ double amplitudePerSecond = accumulatedAmplitude / sampleRate;
115+
116+ AmplitudeData data{};
117+ data.timeInSeconds = timestampInSeconds;
118+ data.amplitude = amplitudePerSecond;
119+
120+ amplitudeData.push_back (data);
121+
122+ accumulatedAmplitude = 0.0 ;
123+ sampleCount = 0 ;
124+ }
121125 }
122126 }
123127 }
124128 }
125129 }
126-
127- // Release the packet
128- av_packet_unref (&packet);
129130 }
130-
131- // Clean up resources
132- avformat_close_input (&formatContext);
133- avcodec_free_context (&codecContext);
134- av_frame_free (&frame);
135-
136- return amplitudeData;
131+
132+ // Release the packet
133+ av_packet_unref (&packet);
137134 }
135+
136+ // Clean up resources
137+ avformat_close_input (&formatContext);
138+ avcodec_free_context (&codecContext);
139+ av_frame_free (&frame);
140+
141+ return amplitudeData;
142+ }
138143}
0 commit comments