1c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung/* 2c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * Copyright (C) 2014 The Android Open Source Project 3c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * 4c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * Licensed under the Apache License, Version 2.0 (the "License"); 5c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * you may not use this file except in compliance with the License. 6c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * You may obtain a copy of the License at 7c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * 8c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * http://www.apache.org/licenses/LICENSE-2.0 9c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * 10c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * Unless required by applicable law or agreed to in writing, software 11c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * distributed under the License is distributed on an "AS IS" BASIS, 12c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * See the License for the specific language governing permissions and 14c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * limitations under the License. 15c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung */ 16c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 17c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#ifndef ANDROID_AUDIO_TEST_UTILS_H 18c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#define ANDROID_AUDIO_TEST_UTILS_H 19c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 20c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#include <audio_utils/sndfile.h> 21c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 22c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#ifndef ARRAY_SIZE 23c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 24c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#endif 25c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 26c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungtemplate<typename T, typename U> 27c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungstruct is_same 28c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung{ 29c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung static const bool value = false; 30c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung}; 31c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 32c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungtemplate<typename T> 33c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungstruct is_same<T, T> // partial specialization 34c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung{ 35c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung static const bool value = true; 36c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung}; 37c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 38c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungtemplate<typename T> 39c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungstatic inline T convertValue(double val) 40c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung{ 41c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (is_same<T, int16_t>::value) { 42c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return floor(val * 32767.0 + 0.5); 43c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } else if (is_same<T, int32_t>::value) { 44c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return floor(val * (1UL<<31) + 0.5); 45c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 46c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return val; // assume float or double 47c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung} 48c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 49c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung// Convert a list of integers in CSV format to a Vector of those values. 50c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung// Returns the number of elements in the list, or -1 on error. 51c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungstatic inline int parseCSV(const char *string, std::vector<int>& values) 52c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung{ 53c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung // pass 1: count the number of values and do syntax check 54c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t numValues = 0; 55c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung bool hadDigit = false; 56c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung for (const char *p = string; ; ) { 57c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung switch (*p++) { 58c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung case '0': case '1': case '2': case '3': case '4': 59c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung case '5': case '6': case '7': case '8': case '9': 60c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung hadDigit = true; 61c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung break; 62c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung case '\0': 63c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (hadDigit) { 64c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung // pass 2: allocate and initialize vector of values 65c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung values.resize(++numValues); 66c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung values[0] = atoi(p = string); 67c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung for (size_t i = 1; i < numValues; ) { 68c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (*p++ == ',') { 69c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung values[i++] = atoi(p); 70c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 71c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 72c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return numValues; 73c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 74c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung // fall through 75c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung case ',': 76c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (hadDigit) { 77c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung hadDigit = false; 78c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung numValues++; 79c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung break; 80c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 81c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung // fall through 82c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung default: 83c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return -1; 84c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 85c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 86c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung} 87c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 88c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung/* Creates a type-independent audio buffer provider from 89c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * a buffer base address, size, framesize, and input increment array. 90c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * 91c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * No allocation or deallocation of the provided buffer is done. 92c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung */ 93c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungclass TestProvider : public android::AudioBufferProvider { 94c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungpublic: 95c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung TestProvider(void* addr, size_t frames, size_t frameSize, 96c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung const std::vector<int>& inputIncr) 97c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung : mAddr(addr), 98c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNumFrames(frames), 99c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mFrameSize(frameSize), 100c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextFrame(0), mUnrel(0), mInputIncr(inputIncr), mNextIdx(0) 101c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 102c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 103c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 104c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung TestProvider() 105c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung : mAddr(NULL), mNumFrames(0), mFrameSize(0), 106c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextFrame(0), mUnrel(0), mNextIdx(0) 107c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 108c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 109c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 110c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung void setIncr(const std::vector<int>& inputIncr) { 111c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mInputIncr = inputIncr; 112c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextIdx = 0; 113c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 114c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 115c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung virtual android::status_t getNextBuffer(Buffer* buffer, int64_t pts __unused = kInvalidPTS) 116c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 117c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t requestedFrames = buffer->frameCount; 118c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (requestedFrames > mNumFrames - mNextFrame) { 119c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung buffer->frameCount = mNumFrames - mNextFrame; 120c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 121c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (!mInputIncr.empty()) { 122c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t provided = mInputIncr[mNextIdx++]; 123a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten ALOGV("getNextBuffer() mValue[%zu]=%zu not %zu", 124c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextIdx-1, provided, buffer->frameCount); 125c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (provided < buffer->frameCount) { 126c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung buffer->frameCount = provided; 127c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 128c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (mNextIdx >= mInputIncr.size()) { 129c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextIdx = 0; 130c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 131c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 132a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten ALOGV("getNextBuffer() requested %zu frames out of %zu frames available" 133a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten " and returned %zu frames", 134c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung requestedFrames, mNumFrames - mNextFrame, buffer->frameCount); 135c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mUnrel = buffer->frameCount; 136c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (buffer->frameCount > 0) { 137c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung buffer->raw = (char *)mAddr + mFrameSize * mNextFrame; 138c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return android::NO_ERROR; 139c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } else { 140c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung buffer->raw = NULL; 141c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return android::NOT_ENOUGH_DATA; 142c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 143c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 144c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 145c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung virtual void releaseBuffer(Buffer* buffer) 146c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 147c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (buffer->frameCount > mUnrel) { 148a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten ALOGE("releaseBuffer() released %zu frames but only %zu available " 149a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten "to release", buffer->frameCount, mUnrel); 150c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextFrame += mUnrel; 151c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mUnrel = 0; 152c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } else { 153c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 154a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten ALOGV("releaseBuffer() released %zu frames out of %zu frames available " 155a4daf0b4f934b800a49f199fb8c09409391c8fc0Glenn Kasten "to release", buffer->frameCount, mUnrel); 156c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextFrame += buffer->frameCount; 157c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mUnrel -= buffer->frameCount; 158c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 159c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung buffer->frameCount = 0; 160c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung buffer->raw = NULL; 161c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 162c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 163c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung void reset() 164c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 165c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNextFrame = 0; 166c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 167c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 168c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t getNumFrames() 169c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 170c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return mNumFrames; 171c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 172c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 173c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 174c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungprotected: 175c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung void* mAddr; // base address 176c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t mNumFrames; // total frames 177c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung int mFrameSize; // frame size (# channels * bytes per sample) 178c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t mNextFrame; // index of next frame to provide 179c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t mUnrel; // number of frames not yet released 180c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung std::vector<int> mInputIncr; // number of frames provided per call 181c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t mNextIdx; // index of next entry in mInputIncr to use 182c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung}; 183c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 184c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung/* Creates a buffer filled with a sine wave. 185c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung */ 186c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungtemplate<typename T> 187c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungstatic void createSine(void *vbuffer, size_t frames, 188c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t channels, double sampleRate, double freq) 189c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung{ 190c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double tscale = 1. / sampleRate; 191c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung T* buffer = reinterpret_cast<T*>(vbuffer); 192c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung for (size_t i = 0; i < frames; ++i) { 193c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double t = i * tscale; 194c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double y = sin(2. * M_PI * freq * t); 195c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung T yt = convertValue<T>(y); 196c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 197c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung for (size_t j = 0; j < channels; ++j) { 198e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung buffer[i*channels + j] = yt / T(j + 1); 199c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 200c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 201c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung} 202c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 203c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung/* Creates a buffer filled with a chirp signal (a sine wave sweep). 204c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * 205c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * When creating the Chirp, note that the frequency is the true sinusoidal 206c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * frequency not the sampling rate. 207c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * 208c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * http://en.wikipedia.org/wiki/Chirp 209c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung */ 210c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungtemplate<typename T> 211c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungstatic void createChirp(void *vbuffer, size_t frames, 212c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung size_t channels, double sampleRate, double minfreq, double maxfreq) 213c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung{ 214c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double tscale = 1. / sampleRate; 215c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung T *buffer = reinterpret_cast<T*>(vbuffer); 216c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung // note the chirp constant k has a divide-by-two. 217c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double k = (maxfreq - minfreq) / (2. * tscale * frames); 218c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung for (size_t i = 0; i < frames; ++i) { 219c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double t = i * tscale; 220c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double y = sin(2. * M_PI * (k * t + minfreq) * t); 221c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung T yt = convertValue<T>(y); 222c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 223c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung for (size_t j = 0; j < channels; ++j) { 224e93b6b7347a7846c8fd746542364ec11b0cd5124Andy Hung buffer[i*channels + j] = yt / T(j + 1); 225c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 226c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 227c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung} 228c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 229c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung/* This derived class creates a buffer provider of datatype T, 230c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * consisting of an input signal, e.g. from createChirp(). 231c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * The number of frames can be obtained from the base class 232c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung * TestProvider::getNumFrames(). 233c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung */ 234c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 235c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungclass SignalProvider : public TestProvider { 236c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungpublic: 237c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung SignalProvider() 238c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung : mSampleRate(0), 239c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mChannels(0) 240c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 241c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 242c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 243c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung virtual ~SignalProvider() 244c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 245c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung free(mAddr); 246c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mAddr = NULL; 247c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 248c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 249c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung template <typename T> 250c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung void setChirp(size_t channels, double minfreq, double maxfreq, double sampleRate, double time) 251c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 252c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung createBufferByFrames<T>(channels, sampleRate, sampleRate*time); 253c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung createChirp<T>(mAddr, mNumFrames, mChannels, mSampleRate, minfreq, maxfreq); 254c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 255c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 256c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung template <typename T> 257c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung void setSine(size_t channels, 258c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung double freq, double sampleRate, double time) 259c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 260c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung createBufferByFrames<T>(channels, sampleRate, sampleRate*time); 261c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung createSine<T>(mAddr, mNumFrames, mChannels, mSampleRate, freq); 262c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 263c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 264c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung template <typename T> 265c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung void setFile(const char *file_in) 266c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 267c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung SF_INFO info; 268c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung info.format = 0; 269c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung SNDFILE *sf = sf_open(file_in, SFM_READ, &info); 270c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (sf == NULL) { 271c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung perror(file_in); 272c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return; 273c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 274c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung createBufferByFrames<T>(info.channels, info.samplerate, info.frames); 275c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung if (is_same<T, float>::value) { 276c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung (void) sf_readf_float(sf, (float *) mAddr, mNumFrames); 277c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } else if (is_same<T, short>::value) { 278c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung (void) sf_readf_short(sf, (short *) mAddr, mNumFrames); 279c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 280c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung sf_close(sf); 281c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 282c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 283c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung template <typename T> 284c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung void createBufferByFrames(size_t channels, uint32_t sampleRate, size_t frames) 285c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung { 286c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mNumFrames = frames; 287c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mChannels = channels; 288c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mFrameSize = mChannels * sizeof(T); 289c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung free(mAddr); 290c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mAddr = malloc(mFrameSize * mNumFrames); 291c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung mSampleRate = sampleRate; 292c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 293c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 294c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung uint32_t getSampleRate() const { 295c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return mSampleRate; 296c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 297c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 298c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung uint32_t getNumChannels() const { 299c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung return mChannels; 300c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung } 301c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 302c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hungprotected: 303c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung uint32_t mSampleRate; 304c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung uint32_t mChannels; 305c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung}; 306c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung 307c0e5ec8e2d8db15b97094374d0a248e041304b62Andy Hung#endif // ANDROID_AUDIO_TEST_UTILS_H 308