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
115d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten    virtual android::status_t getNextBuffer(Buffer* buffer)
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