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