/* * Copyright (C) 2011 in-somnia * * This file is part of JAAD. * * JAAD is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * JAAD is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. * If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.jaad.aac.sbr; import java.util.Arrays; //static calculation methods class Calculation implements SBRTables { static int getStartChannel(int startFrequency, int sampleRate) { final int index = getSampleRateIndex(sampleRate); return START_MIN_TABLE[index]+START_OFFSETS[OFFSET_INDEX_TABLE[index]][startFrequency]; } static int getStopChannel(int stopFrequency, int sampleRate, int k0) { if(stopFrequency==15) return Math.min(64, k0*3); else if(stopFrequency==14) return Math.min(64, k0*2); else { //stopFrequency<=13 final int index = getSampleRateIndex(sampleRate); return Math.min(64, STOP_MIN_TABLE[index]+STOP_OFFSETS[index][Math.min(stopFrequency, 13)]); } } //TODO: replace with SampleFrequency.forFrequency ?? static int getSampleRateIndex(int samplerate) { if(92017<=samplerate) return 0; else if(75132<=samplerate) return 1; else if(55426<=samplerate) return 2; else if(46009<=samplerate) return 3; else if(37566<=samplerate) return 4; else if(27713<=samplerate) return 5; else if(23004<=samplerate) return 6; else if(18783<=samplerate) return 7; else if(13856<=samplerate) return 8; else if(11502<=samplerate) return 9; else if(9391<=samplerate) return 10; else return 11; } //calculates the master frequency table from k0, k2 and alterScale for frequencyScale = 0 static int[] calculateMasterFrequencyTableFS0(int k0, int k2, boolean alterScale) { if(k2<=k0) return null; final int dk = alterScale ? 2 : 1; int i; int nrBands = alterScale ? (((k2-k0+2)>>2)<<1) : (((k2-k0)>>1)<<1); nrBands = Math.min(nrBands, 63); if(nrBands<=0) return new int[0]; final int k2Achieved = k0+nrBands*dk; int k2Diff = k2-k2Achieved; //fill vDk final int[] vDk = new int[64]; for(i = 0; i<nrBands; i++) { vDk[i] = dk; } if(k2Diff!=0) { final int incr = (k2Diff>0) ? -1 : 1; i = ((k2Diff>0) ? (nrBands-1) : 0); while(k2Diff!=0) { vDk[i] -= incr; i += incr; k2Diff += incr; } } //fill table final int len = Math.min(nrBands+1, 64); int[] table = new int[len]; table[0] = k0; for(i = 1; i<len; i++) { table[i] = table[i-1]+vDk[i-1]; } return table; } //calculates the master frequency table from k0, k2 and alterScale for frequencyScale > 0 static int[] calculateMasterFrequencyTable(int k0, int k2, int frequencyScale, boolean alterScale) { if(k2<=k0) return null; final int bands = MFT_BANDS_COUNT[frequencyScale-1]; int i; int k1; boolean twoRegions; if(((float) k2/(float) k0)>2.2449) { twoRegions = true; k1 = k0<<1; } else { twoRegions = false; k1 = k2; } final int nrBand0 = Math.min(2*findBands(false, bands, k0, k1), 63); if(nrBand0<=0) return new int[0]; //fill vDk0 final int[] vDk0 = new int[64]; double q = findInitialPower(nrBand0, k0, k1); double qk = k0; int A_1 = (int) (qk+0.5); int A_0; for(i = 0; i<=nrBand0; i++) { A_0 = A_1; qk *= q; A_1 = (int) Math.round(qk); vDk0[i] = A_1-A_0; } Arrays.sort(vDk0, 0, nrBand0); //needed?? //fill vk0 final int[] vk0 = new int[64]; vk0[0] = k0; for(i = 1; i<=nrBand0; i++) { vk0[i] = vk0[i-1]+vDk0[i-1]; if(vDk0[i-1]==0) return new int[0]; } int[] ret; if(twoRegions) { //two region: create vk1 and append it to vk0 final int nrBand1 = Math.min(2*findBands(true, bands, k1, k2), 63); //fill vDk1 final int[] vDk1 = new int[64]; q = findInitialPower(nrBand1, k1, k2); qk = k1; A_1 = (int) (qk+.5); for(i = 0; i<=nrBand1-1; i++) { A_0 = A_1; qk *= q; A_1 = (int) (qk+0.5); vDk1[i] = A_1-A_0; } if(vDk1[0]<vDk0[nrBand0-1]) { Arrays.sort(vDk1, 0, nrBand1+1); //needed?? final int change = vDk0[nrBand0-1]-vDk1[0]; vDk1[0] = vDk0[nrBand0-1]; vDk1[nrBand1-1] = vDk1[nrBand1-1]-change; } //fill vk1 final int[] vk1 = new int[64]; Arrays.sort(vDk1, 0, nrBand1); //needed?? vk1[0] = k1; for(i = 1; i<=nrBand1; i++) { vk1[i] = vk1[i-1]+vDk1[i-1]; if(vDk1[i-1]==0) return new int[0]; } final int off = nrBand0+1; final int len = Math.min(off+nrBand1, 64); ret = new int[len]; System.arraycopy(vk0, 0, ret, 0, off); System.arraycopy(vk1, 1, ret, off, nrBand1); } else { //one region: just copy vk0 final int len = Math.min(nrBand0+1, 64); ret = new int[len]; System.arraycopy(vk0, 0, ret, 0, len); } return ret; } /* finds the number of bands by: * bands * log(a1/a0)/log(2.0) + 0.5 */ static int findBands(boolean warp, int bands, int a0, int a1) { double div = Math.log(2.0); if(warp) div *= 1.3; return (int) (bands*Math.log((double) a1/(double) a0)/div+0.5); } private static double findInitialPower(int bands, int a0, int a1) { return Math.pow((double) a1/(double) a0, 1.0/(double) bands); } }