Skip to content

Commit 0a3719e

Browse files
committed
feat: add groupBySeconds option
1 parent a81edbf commit 0a3719e

File tree

7 files changed

+50
-35
lines changed

7 files changed

+50
-35
lines changed

android/cpp-adapter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
extern "C"
66
JNIEXPORT jobjectArray JNICALL
7-
Java_com_audioanalyzer_AudioAnalyzerModule_analyzeAudio(JNIEnv *env, jclass obj, jstring filePath) {
7+
Java_com_audioanalyzer_AudioAnalyzerModule_analyzeAudio(JNIEnv *env, jclass obj, jstring filePath, jdouble groupBySeconds) {
88

99
// Step 1: Convert Java string to C++ string
1010
const char *nativeFilePath = env->GetStringUTFChars(filePath, nullptr);
1111

1212

1313
// Step 2: Call the analyzeAudio function
1414
audioanalyzer::FFmpegException errorPtr = nullptr;
15-
std::vector<audioanalyzer::AmplitudeData> amplitudeData = audioanalyzer::analyzeAudio(nativeFilePath, &errorPtr);
15+
std::vector<audioanalyzer::AmplitudeData> amplitudeData = audioanalyzer::analyzeAudio(nativeFilePath, groupBySeconds, &errorPtr);
1616

1717

1818
if (errorPtr.getMessage()) {

android/src/main/java/com/audioanalyzer/AudioAnalyzerModule.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ public String getName() {
3030
System.loadLibrary("cpp");
3131
}
3232

33-
private static native AmplitudeData[] analyzeAudio(String filepath);
33+
private static native AmplitudeData[] analyzeAudio(String filepath, double groupBySeconds);
3434

3535
@ReactMethod
36-
public void analyzeAudio(String filepath, Promise promise) {
36+
public void analyzeAudio(String filepath, double groupBySeconds, Promise promise) {
3737
try {
38-
AmplitudeData[] analyze = analyzeAudio(filepath);
38+
AmplitudeData[] analyze = analyzeAudio(filepath, groupBySeconds);
3939

4040
WritableArray resultArray = new WritableNativeArray();
4141
for (AmplitudeData data : analyze) {

cpp/react-native-audio-analyzer.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,44 @@ const char* FFmpegException::getMessage() const noexcept {
1414
return message;
1515
}
1616

17-
std::vector<AmplitudeData> analyzeAudio(const char *filename, FFmpegException *errorPtr) {
17+
std::vector<AmplitudeData> analyzeAudio(const char *filename, double groupBySeconds, FFmpegException *errorPtr) {
1818
std::vector<AmplitudeData> amplitudeData;
19-
19+
20+
// Проверка корректности groupBySeconds
21+
if (groupBySeconds <= 0) {
22+
*errorPtr = FFmpegException("groupBySeconds must be greater than 0");
23+
return amplitudeData;
24+
}
25+
2026
// Allocate memory for the AVFormatContext
2127
AVFormatContext *formatContext = avformat_alloc_context();
2228
if (!formatContext) {
2329
*errorPtr = FFmpegException("Failed to allocate AVFormatContext");
2430
return amplitudeData;
2531
}
26-
32+
2733
// Open the input file
2834
if (avformat_open_input(&formatContext, filename, nullptr, nullptr) != 0) {
2935
avformat_free_context(formatContext);
3036
*errorPtr = FFmpegException("Failed to open input file");
3137
return amplitudeData;
3238
}
33-
39+
3440
// Find stream information
3541
if (avformat_find_stream_info(formatContext, nullptr) < 0) {
3642
avformat_close_input(&formatContext);
3743
*errorPtr = FFmpegException("Failed to find stream information");
3844
return amplitudeData;
3945
}
40-
46+
4147
// Find the best audio stream
4248
int audioStreamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
4349
if (audioStreamIndex < 0) {
4450
avformat_close_input(&formatContext);
4551
*errorPtr = FFmpegException("Failed to find audio stream");
4652
return amplitudeData;
4753
}
48-
54+
4955
// Get codec parameters and find the corresponding decoder
5056
AVCodecParameters *codecParameters = formatContext->streams[audioStreamIndex]->codecpar;
5157
const AVCodec *codec = avcodec_find_decoder(codecParameters->codec_id);
@@ -54,52 +60,53 @@ std::vector<AmplitudeData> analyzeAudio(const char *filename, FFmpegException *e
5460
*errorPtr = FFmpegException("Failed to find codec");
5561
return amplitudeData;
5662
}
57-
63+
5864
// Allocate memory for the AVCodecContext
5965
AVCodecContext *codecContext = avcodec_alloc_context3(codec);
6066
if (!codecContext) {
6167
avformat_close_input(&formatContext);
6268
*errorPtr = FFmpegException("Failed to allocate AVCodecContext");
6369
return amplitudeData;
6470
}
65-
71+
6672
// Set codec parameters
6773
if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) {
6874
avformat_close_input(&formatContext);
6975
avcodec_free_context(&codecContext);
7076
*errorPtr = FFmpegException("Failed to set codec parameters");
7177
return amplitudeData;
7278
}
73-
79+
7480
// Open the codec
7581
if (avcodec_open2(codecContext, codec, nullptr) < 0) {
7682
avformat_close_input(&formatContext);
7783
avcodec_free_context(&codecContext);
7884
*errorPtr = FFmpegException("Failed to open codec");
7985
return amplitudeData;
8086
}
81-
87+
8288
// Allocate memory for AVPacket and AVFrame
8389
AVPacket packet;
8490
AVFrame *frame = av_frame_alloc();
85-
91+
8692
// Initialize variables for audio analysis
8793
int sampleRate = codecContext->sample_rate;
8894
double accumulatedAmplitude = 0.0;
8995
long sampleCount = 0;
90-
96+
double currentTimeGroup = 0.0;
97+
9198
// Read frames from the input file
9299
while (av_read_frame(formatContext, &packet) >= 0) {
93100
if (packet.stream_index == audioStreamIndex) {
94101
// Send the packet to the codec
95102
if (avcodec_send_packet(codecContext, &packet) < 0) {
96103
break;
97104
}
98-
105+
99106
// Receive frames from the codec
100107
while (avcodec_receive_frame(codecContext, frame) >= 0) {
101108
double timestampInSeconds = frame->pts * av_q2d(formatContext->streams[audioStreamIndex]->time_base);
102-
109+
103110
// Calculate amplitude for each sample in the frame
104111
for (int i = 0; i < frame->nb_samples; i++) {
105112
for (int ch = 0; ch < codecContext->ch_layout.nb_channels; ch++) {
@@ -108,36 +115,37 @@ std::vector<AmplitudeData> analyzeAudio(const char *filename, FFmpegException *e
108115
if (i < frame->linesize[ch]) {
109116
accumulatedAmplitude += frame->data[ch][i];
110117
sampleCount++;
111-
112-
// Calculate amplitude per second and store the data
113-
if (sampleCount >= sampleRate) {
114-
double amplitudePerSecond = accumulatedAmplitude / sampleRate;
115-
118+
119+
// Calculate amplitude for the specified groupBySeconds
120+
if ((timestampInSeconds - currentTimeGroup) >= groupBySeconds) {
121+
double amplitudePerGroup = accumulatedAmplitude / sampleCount;
122+
116123
AmplitudeData data{};
117-
data.timeInSeconds = timestampInSeconds;
118-
data.amplitude = amplitudePerSecond;
119-
124+
data.timeInSeconds = currentTimeGroup;
125+
data.amplitude = amplitudePerGroup;
126+
120127
amplitudeData.push_back(data);
121-
128+
122129
accumulatedAmplitude = 0.0;
123130
sampleCount = 0;
131+
currentTimeGroup += groupBySeconds;
124132
}
125133
}
126134
}
127135
}
128136
}
129137
}
130138
}
131-
139+
132140
// Release the packet
133141
av_packet_unref(&packet);
134142
}
135-
143+
136144
// Clean up resources
137145
avformat_close_input(&formatContext);
138146
avcodec_free_context(&codecContext);
139147
av_frame_free(&frame);
140-
148+
141149
return amplitudeData;
142150
}
143151
}

cpp/react-native-audio-analyzer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace audioanalyzer {
2121
const char* getMessage() const noexcept;
2222
};
2323

24-
std::vector<AmplitudeData> analyzeAudio(const char *filename, FFmpegException *errorPtr);
24+
std::vector<AmplitudeData> analyzeAudio(const char *filename, double groupBySeconds, FFmpegException *errorPtr);
2525
}
2626

2727
#endif // AUDIOANALYZER_H

ios/AudioAnalyzer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#endif
1414

1515
- (void)analyzeAudio:(NSString *)filename
16+
groupBySeconds:(nonnull NSNumber *)groupBySeconds
1617
resolver:(RCTPromiseResolveBlock)resolve
1718
rejecter:(RCTPromiseRejectBlock)reject;
1819

ios/AudioAnalyzer.mm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ @implementation AudioAnalyzer
66
RCT_EXPORT_MODULE()
77

88
RCT_EXPORT_METHOD(analyzeAudio:(NSString *)filename
9+
groupBySeconds:(nonnull NSNumber *)groupBySeconds
910
resolver:(RCTPromiseResolveBlock)resolve
1011
rejecter:(RCTPromiseRejectBlock)reject)
1112
{
@@ -14,7 +15,9 @@ @implementation AudioAnalyzer
1415

1516
const char *cFilename = [filename UTF8String];
1617

17-
std::vector<audioanalyzer::AmplitudeData> result = audioanalyzer::analyzeAudio(cFilename, &ffmpegError);
18+
double groupBySecondsValue = [groupBySeconds doubleValue];
19+
20+
std::vector<audioanalyzer::AmplitudeData> result = audioanalyzer::analyzeAudio(cFilename, groupBySecondsValue, &ffmpegError);
1821

1922
if (ffmpegError.getMessage()) {
2023
NSString *errorMessage = [NSString stringWithUTF8String:ffmpegError.getMessage()];

src/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ export type AmplitudeData = {
2323
// Other amplitude data
2424
};
2525

26-
export function analyzeAudio(filepath: string): Promise<AmplitudeData[]> {
27-
return AudioAnalyzer.analyzeAudio(filepath);
26+
export function analyzeAudio(
27+
filepath: string,
28+
groupBySeconds: number = 1
29+
): Promise<AmplitudeData[]> {
30+
return AudioAnalyzer.analyzeAudio(filepath, groupBySeconds);
2831
}
2932

3033
export * from './helpers';

0 commit comments

Comments
 (0)