1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.verifier.audio.wavelib; 18 19 public class DspWindow { 20 public DspBufferDouble mBuffer; 21 private int mWindowType = WINDOW_RECTANGULAR; 22 private int mSize; 23 private int mOverlap; 24 25 private static final double TWOPI = Math.PI * 2; 26 27 public static final int WINDOW_RECTANGULAR = 0; 28 public static final int WINDOW_TRIANGULAR = 1; 29 public static final int WINDOW_TRIANGULAR_FLAT_TOP = 2; 30 public static final int WINDOW_HAMMING = 3; 31 public static final int WINDOW_HAMMING_FLAT_TOP = 4; 32 public static final int WINDOW_HANNING = 5; 33 public static final int WINDOW_HANNING_FLAT_TOP = 6; 34 DspWindow(int windowType, int size, int overlap)35 public DspWindow(int windowType, int size, int overlap) { 36 init(windowType, size, overlap); 37 } 38 DspWindow(int windowType, int size)39 public DspWindow(int windowType, int size) { 40 init(windowType, size, size / 2); 41 } 42 init(int windowType, int size, int overlap)43 public void init(int windowType, int size, int overlap) { 44 if (size > 0 && overlap > 0) { 45 mSize = size; 46 mOverlap = overlap; 47 if (mOverlap > mSize / 2) { 48 mOverlap = mSize / 2; 49 } 50 51 mBuffer = new DspBufferDouble(mSize); 52 if (fillWindow(mBuffer, windowType, mOverlap)) { 53 mWindowType = windowType; 54 } 55 } 56 } 57 scale(double scale)58 public void scale(double scale) { 59 DspBufferMath.mult(mBuffer, mBuffer, scale); 60 } 61 fillWindow(DspBufferDouble r, int type, int overlap)62 public static boolean fillWindow(DspBufferDouble r, int type, int overlap) { 63 boolean status = false; 64 int size = r.getSize(); 65 if (overlap > size / 2) { 66 overlap = size / 2; 67 } 68 69 switch(type) { 70 case WINDOW_RECTANGULAR: 71 status = fillRectangular(r); 72 break; 73 case WINDOW_TRIANGULAR: 74 status = fillTriangular(r, size / 2); 75 break; 76 case WINDOW_TRIANGULAR_FLAT_TOP: 77 status = fillTriangular(r, overlap); 78 break; 79 case WINDOW_HAMMING: 80 status = fillHamming(r, size / 2); 81 break; 82 case WINDOW_HAMMING_FLAT_TOP: 83 status = fillHamming(r, overlap); 84 break; 85 case WINDOW_HANNING: 86 status = fillHanning(r, size / 2); 87 break; 88 case WINDOW_HANNING_FLAT_TOP: 89 status = fillHanning(r, overlap); 90 break; 91 } 92 return status; 93 } 94 fillRectangular(DspBufferDouble r)95 private static boolean fillRectangular(DspBufferDouble r) { 96 if (DspBufferMath.set(r, 1.0) == DspBufferMath.MATH_RESULT_SUCCESS) { 97 return true; 98 } 99 return false; 100 } 101 fillTriangular(DspBufferDouble b, int overlap)102 private static boolean fillTriangular(DspBufferDouble b, int overlap) { 103 int size = b.getSize(); 104 if (overlap > size / 2) { 105 overlap = size / 2; 106 } 107 108 double value; 109 //ramp up 110 int i = 0; 111 if (overlap > 0) { 112 for (i = 0; i < overlap; i++) { 113 value = (2.0 * i + 1) / (2 * overlap); 114 b.mData[i] = value; 115 } 116 } 117 118 //flat top 119 for (; i < size - overlap; i++) { 120 b.mData[i] = 1.0; 121 } 122 123 //ramp down 124 if (overlap > 0) { 125 for (; i < size; i++) { 126 value = (2.0 * (size - i) - 1) / (2 * overlap); 127 b.mData[i] = value; 128 } 129 } 130 return true; 131 } 132 fillHamming(DspBufferDouble b, int overlap)133 private static boolean fillHamming(DspBufferDouble b, int overlap) { 134 int size = b.getSize(); 135 if (overlap > size / 2) 136 overlap = size / 2; 137 138 //create window, then copy 139 double value; 140 141 int twoOverlap = 2 * overlap; 142 //ramp up 143 int i = 0; 144 if (overlap > 0) { 145 for (i = 0; i < overlap; i++) { 146 value = 0.54 - 0.46 * Math.cos(TWOPI * i / (twoOverlap - 1)); 147 b.mData[i] = value; 148 } 149 } 150 151 //flat top 152 for (; i < size - overlap; i++) { 153 b.mData[i] = 1.0; 154 } 155 156 //ramp down 157 int k; 158 if (overlap > 0) { 159 for (; i < size; i++) { 160 k = i - (size - 2 * overlap); 161 value = 0.54 - 0.46 * Math.cos(TWOPI * k / (twoOverlap - 1)); 162 b.mData[i] = value; 163 } 164 } 165 return true; 166 } 167 fillHanning(DspBufferDouble b, int overlap)168 private static boolean fillHanning(DspBufferDouble b, int overlap) { 169 int size = b.getSize(); 170 if (overlap > size / 2) 171 overlap = size / 2; 172 173 //create window, then copy 174 double value; 175 176 int twoOverlap = 2*overlap; 177 //ramp up 178 int i = 0; 179 if (overlap > 0) { 180 for (i = 0; i < overlap; i++) { 181 value = 0.5 * (1.0 - Math.cos(TWOPI * i / (twoOverlap - 1))); 182 b.mData[i] = value; 183 } 184 } 185 186 //flat top 187 for (; i < size - overlap; i++) { 188 b.mData[i] = 1.0; 189 } 190 191 //ramp down 192 if (overlap > 0) { 193 for (; i < size; i++) { 194 int k = i - (size - 2 * overlap); 195 value = 0.5 * (1.0 - Math.cos(TWOPI * k / (twoOverlap - 1))); 196 b.mData[i] = value; 197 } 198 } 199 return true; 200 } 201 } 202