diff options
Diffstat (limited to 'media/jni/android_media_ResampleInputStream.cpp')
-rw-r--r-- | media/jni/android_media_ResampleInputStream.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/media/jni/android_media_ResampleInputStream.cpp b/media/jni/android_media_ResampleInputStream.cpp new file mode 100644 index 0000000..0247cdb --- /dev/null +++ b/media/jni/android_media_ResampleInputStream.cpp @@ -0,0 +1,143 @@ +/* +** +** 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"; + jclass clazz; + + clazz = env->FindClass(kClassPathName); + if (clazz == NULL) { + LOGE("Can't find %s", kClassPathName); + return -1; + } + + return AndroidRuntime::registerNativeMethods(env, + kClassPathName, gMethods, NELEM(gMethods)); +} + + |