1 /* 2 ** 3 ** Copyright 2007, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "ResampleInputStream" 19 #include "utils/Log.h" 20 21 #include <media/mediarecorder.h> 22 #include <stdio.h> 23 #include <assert.h> 24 #include <limits.h> 25 #include <unistd.h> 26 #include <fcntl.h> 27 #include <utils/threads.h> 28 29 #include "jni.h" 30 #include "JNIHelp.h" 31 #include "android_runtime/AndroidRuntime.h" 32 33 34 // ---------------------------------------------------------------------------- 35 36 using namespace android; 37 38 39 #define FIR_COEF(coef) (short)(0x10000 * coef) 40 static const short fir21[] = { 41 FIR_COEF(-0.006965742326), 42 FIR_COEF(-0.008428945737), 43 FIR_COEF( 0.004241280174), 44 FIR_COEF( 0.022141096893), 45 FIR_COEF( 0.018765669437), 46 FIR_COEF(-0.009871891152), 47 FIR_COEF(-0.024842433247), 48 FIR_COEF( 0.006121772058), 49 FIR_COEF( 0.045890841611), 50 FIR_COEF( 0.021573503509), 51 FIR_COEF(-0.059681984668), 52 FIR_COEF(-0.076036275138), 53 FIR_COEF( 0.072405390275), 54 FIR_COEF( 0.308255674582), 55 FIR_COEF( 0.424321210495), 56 FIR_COEF( 0.308255674582), 57 FIR_COEF( 0.072405390275), 58 FIR_COEF(-0.076036275138), 59 FIR_COEF(-0.059681984668), 60 FIR_COEF( 0.021573503509), 61 FIR_COEF( 0.045890841611), 62 FIR_COEF( 0.006121772058), 63 FIR_COEF(-0.024842433247), 64 FIR_COEF(-0.009871891152), 65 FIR_COEF( 0.018765669437), 66 FIR_COEF( 0.022141096893), 67 FIR_COEF( 0.004241280174), 68 FIR_COEF(-0.008428945737), 69 FIR_COEF(-0.006965742326) 70 }; 71 static const int nFir21 = sizeof(fir21) / sizeof(fir21[0]); 72 73 static const int BUF_SIZE = 2048; 74 75 76 static void android_media_ResampleInputStream_fir21(JNIEnv *env, jclass /* clazz */, 77 jbyteArray jIn, jint jInOffset, 78 jbyteArray jOut, jint jOutOffset, 79 jint jNpoints) { 80 81 // safety first! 82 if (nFir21 + jNpoints * 2 > BUF_SIZE) { 83 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 84 "FIR+data too long %d", nFir21 + jNpoints); 85 return; 86 } 87 88 // get input data 89 short in[BUF_SIZE]; 90 env->GetByteArrayRegion(jIn, jInOffset, (jNpoints * 2 + nFir21 - 1) * 2, (jbyte*)in); 91 92 // compute filter 93 short out[BUF_SIZE]; 94 for (int i = 0; i < jNpoints; i++) { 95 long sum = 0; 96 const short* firp = &fir21[0]; 97 const short* inp = &in[i * 2]; 98 for (int n = nFir21; --n >= 0; ) { 99 sum += ((long)*firp++) * ((long)*inp++); 100 } 101 out[i] = (short)(sum >> 16); 102 } 103 104 // save new values 105 env->SetByteArrayRegion(jOut, jOutOffset, jNpoints * 2, (jbyte*)out); 106 } 107 108 // ---------------------------------------------------------------------------- 109 110 static const JNINativeMethod gMethods[] = { 111 {"fir21", "([BI[BII)V", (void*)android_media_ResampleInputStream_fir21}, 112 }; 113 114 115 int register_android_media_ResampleInputStream(JNIEnv *env) 116 { 117 const char* const kClassPathName = "android/media/ResampleInputStream"; 118 119 return AndroidRuntime::registerNativeMethods(env, 120 kClassPathName, gMethods, NELEM(gMethods)); 121 } 122