xref: /aosp_15_r20/cts/apps/CtsVerifier/jni/audio_loopback/WavFileCapture.cpp (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <android/log.h>
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <fcntl.h>
21 
22 #include "WavFileCapture.h"
23 #include "WavCaptureOutputStream.h"
24 
25 const char * TAG = "WavFileCapture";
26 
27 WavFileCapture sWavFileCapture;
28 
WavFileCapture()29 WavFileCapture::WavFileCapture() : mCaptureActive(false) {
30     mOutputStream = new WavCaptureOutputStream();
31     mWavFileWriter = new WaveFileWriter(mOutputStream);
32 }
33 
~WavFileCapture()34 WavFileCapture::~WavFileCapture() {
35     delete mOutputStream;
36     delete mWavFileWriter;
37 }
38 
setCaptureFile(const char * wavFilePath)39 void WavFileCapture::setCaptureFile(const char* wavFilePath) {
40     mWavCapturePath = wavFilePath;
41 }
42 
setWavSpec(int numChannels,int sampleRate)43 void WavFileCapture::setWavSpec(int numChannels, int sampleRate) {
44     mNumChannels = numChannels;
45     mSampleRate = sampleRate;
46 }
47 
startCapture()48 void WavFileCapture::startCapture() {
49     mOutputStream->init();
50     mWavFileWriter->reset();
51     mCaptureActive = true;
52 }
53 
completeCapture()54 int WavFileCapture::completeCapture() {
55     if (!mCaptureActive) {
56         return CAPTURE_NOTDONE;
57     }
58 
59     int returnVal;
60     FILE* file = fopen(mWavCapturePath.c_str(), "w");
61     if (file == nullptr) {
62         __android_log_print(ANDROID_LOG_ERROR, TAG,
63                             "error opening capture file: %s", mWavCapturePath.c_str());
64         returnVal = CAPTURE_BADOPEN;
65     } else {
66         int numWriteBytes = mOutputStream->length();
67         int numWrittenBytes =
68                 fwrite(mOutputStream->getData(), sizeof(uint8_t), numWriteBytes, file);
69         if (numWrittenBytes != numWriteBytes) {
70             __android_log_print(ANDROID_LOG_ERROR, TAG,
71                                 "error writing capture file: %s", mWavCapturePath.c_str());
72             returnVal = CAPTURE_BADWRITE;
73         } else {
74             returnVal = CAPTURE_SUCCESS;
75         }
76         fclose(file);
77     }
78     mCaptureActive = false;
79 
80     return returnVal;
81 }
82 
abandonCaptureData()83 void WavFileCapture::abandonCaptureData() {
84     // TODO: implement when we have a caller for this.
85     mCaptureActive = false;
86 }
87 
captureData(void * audioData,int32_t numFrames)88 void WavFileCapture::captureData(void *audioData, int32_t numFrames) {
89     if (mCaptureActive) {
90         mWavFileWriter->write((float*)audioData, 0, numFrames /* * numChannels? */);
91     }
92 }
93 
94 /*
95  * JNI Interface
96  */
97 #include <jni.h>
98 
99 extern "C" {
100 
101 JNIEXPORT jlong JNICALL
Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_getCapture_1n()102     Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_getCapture_1n() {
103     return (jlong)&sWavFileCapture;
104 }
105 
106 JNIEXPORT void JNICALL
Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_setCaptureFile_1n(JNIEnv * env __unused,jobject obj __unused,jlong wavCaptureObj,jstring wavFilePath)107     Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_setCaptureFile_1n(
108             JNIEnv *env __unused, jobject obj __unused, jlong wavCaptureObj, jstring wavFilePath) {
109     WavFileCapture* capture = (WavFileCapture*)wavCaptureObj;
110 
111     const char *captureFile = env->GetStringUTFChars(wavFilePath, 0);
112     capture->setCaptureFile(captureFile);
113 
114     env->ReleaseStringUTFChars(wavFilePath, captureFile);
115 }
116 
117 JNIEXPORT void JNICALL
Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_setWavSpec_1n(JNIEnv * env __unused,jobject obj __unused,jlong wavCaptureObj,jint numChannels,jint sampleRate)118     Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_setWavSpec_1n(
119             JNIEnv *env __unused, jobject obj __unused, jlong wavCaptureObj, jint numChannels, jint sampleRate) {
120     WavFileCapture* capture = (WavFileCapture*)wavCaptureObj;
121     capture->setWavSpec(numChannels, sampleRate);
122 }
123 
124 JNIEXPORT void JNICALL
Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_startCapture_1n(JNIEnv * env __unused,jobject obj __unused,jlong wavCaptureObj)125     Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_startCapture_1n(
126             JNIEnv *env __unused, jobject obj __unused, jlong wavCaptureObj) {
127     WavFileCapture* capture = (WavFileCapture*)wavCaptureObj;
128     capture->startCapture();
129 }
130 
131 JNIEXPORT jint JNICALL
Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_completeCapture_1n(JNIEnv * env __unused,jobject obj __unused,jlong wavCaptureObj)132     Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_completeCapture_1n(
133             JNIEnv *env __unused, jobject obj __unused, jlong wavCaptureObj) {
134     WavFileCapture* capture = (WavFileCapture*)wavCaptureObj;
135     return capture->completeCapture();
136 }
137 
138 JNIEXPORT void JNICALL
Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_abandonCapture_n(JNIEnv * env __unused,jobject obj __unused,jlong wavCaptureObj)139     Java_com_android_cts_verifier_audio_audiolib_WavFileCapture_abandonCapture_n(
140             JNIEnv *env __unused, jobject obj __unused, jlong wavCaptureObj) {
141     WavFileCapture* capture = (WavFileCapture*)wavCaptureObj;
142     capture->abandonCaptureData();
143 }
144 
145 } // extern "C"
146