Home | History | Annotate | Download | only in jni
      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 <nativehelper/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