/* ** ** Copyright 2007, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #define LOG_TAG "ResampleInputStream" #include "utils/Log.h" #include <media/mediarecorder.h> #include <stdio.h> #include <assert.h> #include <limits.h> #include <unistd.h> #include <fcntl.h> #include <utils/threads.h> #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" // ---------------------------------------------------------------------------- using namespace android; // // helper function to throw an exception // static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) { if (jclass cls = env->FindClass(ex)) { char msg[1000]; sprintf(msg, fmt, data); env->ThrowNew(cls, msg); env->DeleteLocalRef(cls); } } #define FIR_COEF(coef) (short)(0x10000 * coef) static const short fir21[] = { FIR_COEF(-0.006965742326), FIR_COEF(-0.008428945737), FIR_COEF( 0.004241280174), FIR_COEF( 0.022141096893), FIR_COEF( 0.018765669437), FIR_COEF(-0.009871891152), FIR_COEF(-0.024842433247), FIR_COEF( 0.006121772058), FIR_COEF( 0.045890841611), FIR_COEF( 0.021573503509), FIR_COEF(-0.059681984668), FIR_COEF(-0.076036275138), FIR_COEF( 0.072405390275), FIR_COEF( 0.308255674582), FIR_COEF( 0.424321210495), FIR_COEF( 0.308255674582), FIR_COEF( 0.072405390275), FIR_COEF(-0.076036275138), FIR_COEF(-0.059681984668), FIR_COEF( 0.021573503509), FIR_COEF( 0.045890841611), FIR_COEF( 0.006121772058), FIR_COEF(-0.024842433247), FIR_COEF(-0.009871891152), FIR_COEF( 0.018765669437), FIR_COEF( 0.022141096893), FIR_COEF( 0.004241280174), FIR_COEF(-0.008428945737), FIR_COEF(-0.006965742326) }; static const int nFir21 = sizeof(fir21) / sizeof(fir21[0]); static const int BUF_SIZE = 2048; static void android_media_ResampleInputStream_fir21(JNIEnv *env, jclass clazz, jbyteArray jIn, jint jInOffset, jbyteArray jOut, jint jOutOffset, jint jNpoints) { // safety first! if (nFir21 + jNpoints > BUF_SIZE) { throwException(env, "java/lang/IllegalArgumentException", "FIR+data too long %d", nFir21 + jNpoints); return; } // get input data short in[BUF_SIZE]; env->GetByteArrayRegion(jIn, jInOffset, (jNpoints * 2 + nFir21 - 1) * 2, (jbyte*)in); // compute filter short out[BUF_SIZE]; for (int i = 0; i < jNpoints; i++) { long sum = 0; const short* firp = &fir21[0]; const short* inp = &in[i * 2]; for (int n = nFir21; --n >= 0; ) { sum += ((long)*firp++) * ((long)*inp++); } out[i] = (short)(sum >> 16); } // save new values env->SetByteArrayRegion(jOut, jOutOffset, jNpoints * 2, (jbyte*)out); } // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { {"fir21", "([BI[BII)V", (void*)android_media_ResampleInputStream_fir21}, }; int register_android_media_ResampleInputStream(JNIEnv *env) { const char* const kClassPathName = "android/media/ResampleInputStream"; return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); }