summaryrefslogtreecommitdiffstats
path: root/services/audioflinger/tests
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2014-06-17 14:33:39 -0700
committerAndy Hung <hunga@google.com>2014-06-18 18:28:57 -0700
commitc0e5ec8e2d8db15b97094374d0a248e041304b62 (patch)
tree3e4b2fa1c742d06b009570574250daff0d734dcb /services/audioflinger/tests
parent3a227969f604d7c6a24a795661a13f70a5f37e1f (diff)
downloadframeworks_av-c0e5ec8e2d8db15b97094374d0a248e041304b62.zip
frameworks_av-c0e5ec8e2d8db15b97094374d0a248e041304b62.tar.gz
frameworks_av-c0e5ec8e2d8db15b97094374d0a248e041304b62.tar.bz2
Extract out test utility functions from resampler_tests
These will be used for mixer tests later. Change-Id: I22b1c89857058cfb2450afe15e80d6c9306a31f1
Diffstat (limited to 'services/audioflinger/tests')
-rw-r--r--services/audioflinger/tests/Android.mk4
-rw-r--r--services/audioflinger/tests/resampler_tests.cpp213
-rw-r--r--services/audioflinger/tests/test_utils.h307
3 files changed, 322 insertions, 202 deletions
diff --git a/services/audioflinger/tests/Android.mk b/services/audioflinger/tests/Android.mk
index 874f18f..f365637 100644
--- a/services/audioflinger/tests/Android.mk
+++ b/services/audioflinger/tests/Android.mk
@@ -1,5 +1,8 @@
# Build the unit tests for audioflinger
+#
+# resampler unit test
+#
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -20,6 +23,7 @@ LOCAL_C_INCLUDES := \
bionic/libstdc++/include \
external/gtest/include \
external/stlport/stlport \
+ $(call include-path-for, audio-utils) \
frameworks/av/services/audioflinger
LOCAL_SRC_FILES := \
diff --git a/services/audioflinger/tests/resampler_tests.cpp b/services/audioflinger/tests/resampler_tests.cpp
index 8f9c270..4a67d0b 100644
--- a/services/audioflinger/tests/resampler_tests.cpp
+++ b/services/audioflinger/tests/resampler_tests.cpp
@@ -33,200 +33,7 @@
#include <gtest/gtest.h>
#include <media/AudioBufferProvider.h>
#include "AudioResampler.h"
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
-template<typename T, typename U>
-struct is_same
-{
- static const bool value = false;
-};
-
-template<typename T>
-struct is_same<T, T> // partial specialization
-{
- static const bool value = true;
-};
-
-template<typename T>
-static inline T convertValue(double val)
-{
- if (is_same<T, int16_t>::value) {
- return floor(val * 32767.0 + 0.5);
- } else if (is_same<T, int32_t>::value) {
- return floor(val * (1UL<<31) + 0.5);
- }
- return val; // assume float or double
-}
-
-/* Creates a type-independent audio buffer provider from
- * a buffer base address, size, framesize, and input increment array.
- *
- * No allocation or deallocation of the provided buffer is done.
- */
-class TestProvider : public android::AudioBufferProvider {
-public:
- TestProvider(const void* addr, size_t frames, size_t frameSize,
- const std::vector<size_t>& inputIncr)
- : mAddr(addr),
- mNumFrames(frames),
- mFrameSize(frameSize),
- mNextFrame(0), mUnrel(0), mInputIncr(inputIncr), mNextIdx(0)
- {
- }
-
- virtual android::status_t getNextBuffer(Buffer* buffer, int64_t pts __unused = kInvalidPTS )
- {
- size_t requestedFrames = buffer->frameCount;
- if (requestedFrames > mNumFrames - mNextFrame) {
- buffer->frameCount = mNumFrames - mNextFrame;
- }
- if (!mInputIncr.empty()) {
- size_t provided = mInputIncr[mNextIdx++];
- ALOGV("getNextBuffer() mValue[%d]=%u not %u",
- mNextIdx-1, provided, buffer->frameCount);
- if (provided < buffer->frameCount) {
- buffer->frameCount = provided;
- }
- if (mNextIdx >= mInputIncr.size()) {
- mNextIdx = 0;
- }
- }
- ALOGV("getNextBuffer() requested %u frames out of %u frames available"
- " and returned %u frames\n",
- requestedFrames, mNumFrames - mNextFrame, buffer->frameCount);
- mUnrel = buffer->frameCount;
- if (buffer->frameCount > 0) {
- buffer->raw = (char *)mAddr + mFrameSize * mNextFrame;
- return android::NO_ERROR;
- } else {
- buffer->raw = NULL;
- return android::NOT_ENOUGH_DATA;
- }
- }
-
- virtual void releaseBuffer(Buffer* buffer)
- {
- if (buffer->frameCount > mUnrel) {
- ALOGE("releaseBuffer() released %u frames but only %u available "
- "to release\n", buffer->frameCount, mUnrel);
- mNextFrame += mUnrel;
- mUnrel = 0;
- } else {
-
- ALOGV("releaseBuffer() released %u frames out of %u frames available "
- "to release\n", buffer->frameCount, mUnrel);
- mNextFrame += buffer->frameCount;
- mUnrel -= buffer->frameCount;
- }
- buffer->frameCount = 0;
- buffer->raw = NULL;
- }
-
- void reset()
- {
- mNextFrame = 0;
- }
-
- size_t getNumFrames()
- {
- return mNumFrames;
- }
-
- void setIncr(const std::vector<size_t> inputIncr)
- {
- mNextIdx = 0;
- mInputIncr = inputIncr;
- }
-
-protected:
- const void* mAddr; // base address
- size_t mNumFrames; // total frames
- int mFrameSize; // frame size (# channels * bytes per sample)
- size_t mNextFrame; // index of next frame to provide
- size_t mUnrel; // number of frames not yet released
- std::vector<size_t> mInputIncr; // number of frames provided per call
- size_t mNextIdx; // index of next entry in mInputIncr to use
-};
-
-/* Creates a buffer filled with a sine wave.
- *
- * Returns a pair consisting of the sine signal buffer and the number of frames.
- * The caller must delete[] the buffer when no longer needed (no shared_ptr<>).
- */
-template<typename T>
-static std::pair<T*, size_t> createSine(size_t channels,
- double freq, double samplingRate, double time)
-{
- double tscale = 1. / samplingRate;
- size_t frames = static_cast<size_t>(samplingRate * time);
- T* buffer = new T[frames * channels];
- for (size_t i = 0; i < frames; ++i) {
- double t = i * tscale;
- double y = sin(2. * M_PI * freq * t);
- T yt = convertValue<T>(y);
-
- for (size_t j = 0; j < channels; ++j) {
- buffer[i*channels + j] = yt / (j + 1);
- }
- }
- return std::make_pair(buffer, frames);
-}
-
-/* Creates a buffer filled with a chirp signal (a sine wave sweep).
- *
- * Returns a pair consisting of the chirp signal buffer and the number of frames.
- * The caller must delete[] the buffer when no longer needed (no shared_ptr<>).
- *
- * When creating the Chirp, note that the frequency is the true sinusoidal
- * frequency not the sampling rate.
- *
- * http://en.wikipedia.org/wiki/Chirp
- */
-template<typename T>
-static std::pair<T*, size_t> createChirp(size_t channels,
- double minfreq, double maxfreq, double samplingRate, double time)
-{
- double tscale = 1. / samplingRate;
- size_t frames = static_cast<size_t>(samplingRate * time);
- T *buffer = new T[frames * channels];
- // note the chirp constant k has a divide-by-two.
- double k = (maxfreq - minfreq) / (2. * time);
- for (size_t i = 0; i < frames; ++i) {
- double t = i * tscale;
- double y = sin(2. * M_PI * (k * t + minfreq) * t);
- T yt = convertValue<T>(y);
-
- for (size_t j = 0; j < channels; ++j) {
- buffer[i*channels + j] = yt / (j + 1);
- }
- }
- return std::make_pair(buffer, frames);
-}
-
-/* This derived class creates a buffer provider of datatype T,
- * consisting of an input signal, e.g. from createChirp().
- * The number of frames can be obtained from the base class
- * TestProvider::getNumFrames().
- */
-template <typename T>
-class SignalProvider : public TestProvider {
-public:
- SignalProvider(const std::pair<T*, size_t>& bufferInfo, size_t channels,
- const std::vector<size_t>& values)
- : TestProvider(bufferInfo.first, bufferInfo.second, channels * sizeof(T), values),
- mManagedPtr(bufferInfo.first)
- {
- }
-
- virtual ~SignalProvider()
- {
- delete[] mManagedPtr;
- }
-
-protected:
- T* mManagedPtr;
-};
+#include "test_utils.h"
void resample(void *output, size_t outputFrames, const std::vector<size_t> &outputIncr,
android::AudioBufferProvider *provider, android::AudioResampler *resampler)
@@ -261,10 +68,11 @@ void testBufferIncrement(size_t channels, unsigned inputFreq, unsigned outputFre
enum android::AudioResampler::src_quality quality)
{
// create the provider
- std::vector<size_t> inputIncr;
- SignalProvider<int16_t> provider(createChirp<int16_t>(channels,
- 0., outputFreq/2., outputFreq, outputFreq/2000.),
- channels, inputIncr);
+ std::vector<int> inputIncr;
+ SignalProvider provider;
+ provider.setChirp<int16_t>(channels,
+ 0., outputFreq/2., outputFreq, outputFreq/2000.);
+ provider.setIncr(inputIncr);
// calculate the output size
size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
@@ -339,10 +147,11 @@ void testStopbandDownconversion(size_t channels,
enum android::AudioResampler::src_quality quality)
{
// create the provider
- std::vector<size_t> inputIncr;
- SignalProvider<int16_t> provider(createChirp<int16_t>(channels,
- 0., inputFreq/2., inputFreq, inputFreq/2000.),
- channels, inputIncr);
+ std::vector<int> inputIncr;
+ SignalProvider provider;
+ provider.setChirp<int16_t>(channels,
+ 0., inputFreq/2., inputFreq, inputFreq/2000.);
+ provider.setIncr(inputIncr);
// calculate the output size
size_t outputFrames = ((int64_t) provider.getNumFrames() * outputFreq) / inputFreq;
diff --git a/services/audioflinger/tests/test_utils.h b/services/audioflinger/tests/test_utils.h
new file mode 100644
index 0000000..f954292
--- /dev/null
+++ b/services/audioflinger/tests/test_utils.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_TEST_UTILS_H
+#define ANDROID_AUDIO_TEST_UTILS_H
+
+#include <audio_utils/sndfile.h>
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+template<typename T, typename U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> // partial specialization
+{
+ static const bool value = true;
+};
+
+template<typename T>
+static inline T convertValue(double val)
+{
+ if (is_same<T, int16_t>::value) {
+ return floor(val * 32767.0 + 0.5);
+ } else if (is_same<T, int32_t>::value) {
+ return floor(val * (1UL<<31) + 0.5);
+ }
+ return val; // assume float or double
+}
+
+// Convert a list of integers in CSV format to a Vector of those values.
+// Returns the number of elements in the list, or -1 on error.
+static inline int parseCSV(const char *string, std::vector<int>& values)
+{
+ // pass 1: count the number of values and do syntax check
+ size_t numValues = 0;
+ bool hadDigit = false;
+ for (const char *p = string; ; ) {
+ switch (*p++) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ hadDigit = true;
+ break;
+ case '\0':
+ if (hadDigit) {
+ // pass 2: allocate and initialize vector of values
+ values.resize(++numValues);
+ values[0] = atoi(p = string);
+ for (size_t i = 1; i < numValues; ) {
+ if (*p++ == ',') {
+ values[i++] = atoi(p);
+ }
+ }
+ return numValues;
+ }
+ // fall through
+ case ',':
+ if (hadDigit) {
+ hadDigit = false;
+ numValues++;
+ break;
+ }
+ // fall through
+ default:
+ return -1;
+ }
+ }
+}
+
+/* Creates a type-independent audio buffer provider from
+ * a buffer base address, size, framesize, and input increment array.
+ *
+ * No allocation or deallocation of the provided buffer is done.
+ */
+class TestProvider : public android::AudioBufferProvider {
+public:
+ TestProvider(void* addr, size_t frames, size_t frameSize,
+ const std::vector<int>& inputIncr)
+ : mAddr(addr),
+ mNumFrames(frames),
+ mFrameSize(frameSize),
+ mNextFrame(0), mUnrel(0), mInputIncr(inputIncr), mNextIdx(0)
+ {
+ }
+
+ TestProvider()
+ : mAddr(NULL), mNumFrames(0), mFrameSize(0),
+ mNextFrame(0), mUnrel(0), mNextIdx(0)
+ {
+ }
+
+ void setIncr(const std::vector<int>& inputIncr) {
+ mInputIncr = inputIncr;
+ mNextIdx = 0;
+ }
+
+ virtual android::status_t getNextBuffer(Buffer* buffer, int64_t pts __unused = kInvalidPTS)
+ {
+ size_t requestedFrames = buffer->frameCount;
+ if (requestedFrames > mNumFrames - mNextFrame) {
+ buffer->frameCount = mNumFrames - mNextFrame;
+ }
+ if (!mInputIncr.empty()) {
+ size_t provided = mInputIncr[mNextIdx++];
+ ALOGV("getNextBuffer() mValue[%d]=%u not %u",
+ mNextIdx-1, provided, buffer->frameCount);
+ if (provided < buffer->frameCount) {
+ buffer->frameCount = provided;
+ }
+ if (mNextIdx >= mInputIncr.size()) {
+ mNextIdx = 0;
+ }
+ }
+ ALOGV("getNextBuffer() requested %u frames out of %u frames available"
+ " and returned %u frames\n",
+ requestedFrames, mNumFrames - mNextFrame, buffer->frameCount);
+ mUnrel = buffer->frameCount;
+ if (buffer->frameCount > 0) {
+ buffer->raw = (char *)mAddr + mFrameSize * mNextFrame;
+ return android::NO_ERROR;
+ } else {
+ buffer->raw = NULL;
+ return android::NOT_ENOUGH_DATA;
+ }
+ }
+
+ virtual void releaseBuffer(Buffer* buffer)
+ {
+ if (buffer->frameCount > mUnrel) {
+ ALOGE("releaseBuffer() released %u frames but only %u available "
+ "to release\n", buffer->frameCount, mUnrel);
+ mNextFrame += mUnrel;
+ mUnrel = 0;
+ } else {
+
+ ALOGV("releaseBuffer() released %u frames out of %u frames available "
+ "to release\n", buffer->frameCount, mUnrel);
+ mNextFrame += buffer->frameCount;
+ mUnrel -= buffer->frameCount;
+ }
+ buffer->frameCount = 0;
+ buffer->raw = NULL;
+ }
+
+ void reset()
+ {
+ mNextFrame = 0;
+ }
+
+ size_t getNumFrames()
+ {
+ return mNumFrames;
+ }
+
+
+protected:
+ void* mAddr; // base address
+ size_t mNumFrames; // total frames
+ int mFrameSize; // frame size (# channels * bytes per sample)
+ size_t mNextFrame; // index of next frame to provide
+ size_t mUnrel; // number of frames not yet released
+ std::vector<int> mInputIncr; // number of frames provided per call
+ size_t mNextIdx; // index of next entry in mInputIncr to use
+};
+
+/* Creates a buffer filled with a sine wave.
+ */
+template<typename T>
+static void createSine(void *vbuffer, size_t frames,
+ size_t channels, double sampleRate, double freq)
+{
+ double tscale = 1. / sampleRate;
+ T* buffer = reinterpret_cast<T*>(vbuffer);
+ for (size_t i = 0; i < frames; ++i) {
+ double t = i * tscale;
+ double y = sin(2. * M_PI * freq * t);
+ T yt = convertValue<T>(y);
+
+ for (size_t j = 0; j < channels; ++j) {
+ buffer[i*channels + j] = yt / (j + 1);
+ }
+ }
+}
+
+/* Creates a buffer filled with a chirp signal (a sine wave sweep).
+ *
+ * When creating the Chirp, note that the frequency is the true sinusoidal
+ * frequency not the sampling rate.
+ *
+ * http://en.wikipedia.org/wiki/Chirp
+ */
+template<typename T>
+static void createChirp(void *vbuffer, size_t frames,
+ size_t channels, double sampleRate, double minfreq, double maxfreq)
+{
+ double tscale = 1. / sampleRate;
+ T *buffer = reinterpret_cast<T*>(vbuffer);
+ // note the chirp constant k has a divide-by-two.
+ double k = (maxfreq - minfreq) / (2. * tscale * frames);
+ for (size_t i = 0; i < frames; ++i) {
+ double t = i * tscale;
+ double y = sin(2. * M_PI * (k * t + minfreq) * t);
+ T yt = convertValue<T>(y);
+
+ for (size_t j = 0; j < channels; ++j) {
+ buffer[i*channels + j] = yt / (j + 1);
+ }
+ }
+}
+
+/* This derived class creates a buffer provider of datatype T,
+ * consisting of an input signal, e.g. from createChirp().
+ * The number of frames can be obtained from the base class
+ * TestProvider::getNumFrames().
+ */
+
+class SignalProvider : public TestProvider {
+public:
+ SignalProvider()
+ : mSampleRate(0),
+ mChannels(0)
+ {
+ }
+
+ virtual ~SignalProvider()
+ {
+ free(mAddr);
+ mAddr = NULL;
+ }
+
+ template <typename T>
+ void setChirp(size_t channels, double minfreq, double maxfreq, double sampleRate, double time)
+ {
+ createBufferByFrames<T>(channels, sampleRate, sampleRate*time);
+ createChirp<T>(mAddr, mNumFrames, mChannels, mSampleRate, minfreq, maxfreq);
+ }
+
+ template <typename T>
+ void setSine(size_t channels,
+ double freq, double sampleRate, double time)
+ {
+ createBufferByFrames<T>(channels, sampleRate, sampleRate*time);
+ createSine<T>(mAddr, mNumFrames, mChannels, mSampleRate, freq);
+ }
+
+ template <typename T>
+ void setFile(const char *file_in)
+ {
+ SF_INFO info;
+ info.format = 0;
+ SNDFILE *sf = sf_open(file_in, SFM_READ, &info);
+ if (sf == NULL) {
+ perror(file_in);
+ return;
+ }
+ createBufferByFrames<T>(info.channels, info.samplerate, info.frames);
+ if (is_same<T, float>::value) {
+ (void) sf_readf_float(sf, (float *) mAddr, mNumFrames);
+ } else if (is_same<T, short>::value) {
+ (void) sf_readf_short(sf, (short *) mAddr, mNumFrames);
+ }
+ sf_close(sf);
+ }
+
+ template <typename T>
+ void createBufferByFrames(size_t channels, uint32_t sampleRate, size_t frames)
+ {
+ mNumFrames = frames;
+ mChannels = channels;
+ mFrameSize = mChannels * sizeof(T);
+ free(mAddr);
+ mAddr = malloc(mFrameSize * mNumFrames);
+ mSampleRate = sampleRate;
+ }
+
+ uint32_t getSampleRate() const {
+ return mSampleRate;
+ }
+
+ uint32_t getNumChannels() const {
+ return mChannels;
+ }
+
+protected:
+ uint32_t mSampleRate;
+ uint32_t mChannels;
+};
+
+#endif // ANDROID_AUDIO_TEST_UTILS_H