android_media_ResampleInputStream.cpp revision 4935d05eaa306cef88cf0ab13eca386f270409ec
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 36using namespace android; 37 38 39// 40// helper function to throw an exception 41// 42static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) { 43 if (jclass cls = env->FindClass(ex)) { 44 char msg[1000]; 45 sprintf(msg, fmt, data); 46 env->ThrowNew(cls, msg); 47 env->DeleteLocalRef(cls); 48 } 49} 50 51 52#define FIR_COEF(coef) (short)(0x10000 * coef) 53static const short fir21[] = { 54 FIR_COEF(-0.006965742326), 55 FIR_COEF(-0.008428945737), 56 FIR_COEF( 0.004241280174), 57 FIR_COEF( 0.022141096893), 58 FIR_COEF( 0.018765669437), 59 FIR_COEF(-0.009871891152), 60 FIR_COEF(-0.024842433247), 61 FIR_COEF( 0.006121772058), 62 FIR_COEF( 0.045890841611), 63 FIR_COEF( 0.021573503509), 64 FIR_COEF(-0.059681984668), 65 FIR_COEF(-0.076036275138), 66 FIR_COEF( 0.072405390275), 67 FIR_COEF( 0.308255674582), 68 FIR_COEF( 0.424321210495), 69 FIR_COEF( 0.308255674582), 70 FIR_COEF( 0.072405390275), 71 FIR_COEF(-0.076036275138), 72 FIR_COEF(-0.059681984668), 73 FIR_COEF( 0.021573503509), 74 FIR_COEF( 0.045890841611), 75 FIR_COEF( 0.006121772058), 76 FIR_COEF(-0.024842433247), 77 FIR_COEF(-0.009871891152), 78 FIR_COEF( 0.018765669437), 79 FIR_COEF( 0.022141096893), 80 FIR_COEF( 0.004241280174), 81 FIR_COEF(-0.008428945737), 82 FIR_COEF(-0.006965742326) 83}; 84static const int nFir21 = sizeof(fir21) / sizeof(fir21[0]); 85 86static const int BUF_SIZE = 2048; 87 88 89static void android_media_ResampleInputStream_fir21(JNIEnv *env, jclass clazz, 90 jbyteArray jIn, jint jInOffset, 91 jbyteArray jOut, jint jOutOffset, 92 jint jNpoints) { 93 94 // safety first! 95 if (nFir21 + jNpoints > BUF_SIZE) { 96 throwException(env, "java/lang/IllegalArgumentException", 97 "FIR+data too long %d", nFir21 + jNpoints); 98 return; 99 } 100 101 // get input data 102 short in[BUF_SIZE]; 103 env->GetByteArrayRegion(jIn, jInOffset, (jNpoints * 2 + nFir21 - 1) * 2, (jbyte*)in); 104 105 // compute filter 106 short out[BUF_SIZE]; 107 for (int i = 0; i < jNpoints; i++) { 108 long sum = 0; 109 const short* firp = &fir21[0]; 110 const short* inp = &in[i * 2]; 111 for (int n = nFir21; --n >= 0; ) { 112 sum += ((long)*firp++) * ((long)*inp++); 113 } 114 out[i] = (short)(sum >> 16); 115 } 116 117 // save new values 118 env->SetByteArrayRegion(jOut, jOutOffset, jNpoints * 2, (jbyte*)out); 119} 120 121// ---------------------------------------------------------------------------- 122 123static JNINativeMethod gMethods[] = { 124 {"fir21", "([BI[BII)V", (void*)android_media_ResampleInputStream_fir21}, 125}; 126 127 128int register_android_media_ResampleInputStream(JNIEnv *env) 129{ 130 const char* const kClassPathName = "android/media/ResampleInputStream"; 131 132 return AndroidRuntime::registerNativeMethods(env, 133 kClassPathName, gMethods, NELEM(gMethods)); 134} 135 136 137