media/libcubeb/tests/test_audio.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*
     2  * Copyright © 2013 Sebastien Alaiwan <sebastien.alaiwan@gmail.com>
     3  *
     4  * This program is made available under an ISC-style license.  See the
     5  * accompanying file LICENSE for details.
     6  */
     8 /* libcubeb api/function exhaustive test. Plays a series of tones in different
     9  * conditions. */
    10 #ifdef NDEBUG
    11 #undef NDEBUG
    12 #endif
    13 #define _XOPEN_SOURCE 500
    14 #include <stdio.h>
    15 #include <stdlib.h>
    16 #include <math.h>
    17 #include <assert.h>
    18 #include <string.h>
    20 #include "cubeb/cubeb.h"
    21 #include "common.h"
    23 #define MAX_NUM_CHANNELS 32
    25 #if !defined(M_PI)
    26 #define M_PI 3.14159265358979323846
    27 #endif
    29 #define NELEMS(x) ((int) (sizeof(x) / sizeof(x[0])))
    30 #define VOLUME 0.2
    32 float get_frequency(int channel_index)
    33 {
    34   return 220.0f * (channel_index+1);
    35 }
    37 /* store the phase of the generated waveform */
    38 typedef struct {
    39   int num_channels;
    40   float phase[MAX_NUM_CHANNELS];
    41   float sample_rate;
    42 } synth_state;
    44 synth_state* synth_create(int num_channels, float sample_rate)
    45 {
    46   synth_state* synth = (synth_state *) malloc(sizeof(synth_state));
    47   for(int i=0;i < MAX_NUM_CHANNELS;++i)
    48     synth->phase[i] = 0.0f;
    49   synth->num_channels = num_channels;
    50   synth->sample_rate = sample_rate;
    51   return synth;
    52 }
    54 void synth_destroy(synth_state* synth)
    55 {
    56   free(synth);
    57 }
    59 void synth_run_float(synth_state* synth, float* audiobuffer, long nframes)
    60 {
    61   for(int c=0;c < synth->num_channels;++c) {
    62     float freq = get_frequency(c);
    63     float phase_inc = 2.0 * M_PI * freq / synth->sample_rate;
    64     for(long n=0;n < nframes;++n) {
    65       audiobuffer[n*synth->num_channels+c] = sin(synth->phase[c]) * VOLUME;
    66       synth->phase[c] += phase_inc;
    67     }
    68   }
    69 }
    71 long data_cb_float(cubeb_stream *stream, void *user, void *buffer, long nframes)
    72 {
    73   synth_state *synth = (synth_state *)user;
    74   synth_run_float(synth, (float*)buffer, nframes);
    75   return nframes;
    76 }
    78 void synth_run_16bit(synth_state* synth, short* audiobuffer, long nframes)
    79 {
    80   for(int c=0;c < synth->num_channels;++c) {
    81     float freq = get_frequency(c);
    82     float phase_inc = 2.0 * M_PI * freq / synth->sample_rate;
    83     for(long n=0;n < nframes;++n) {
    84       audiobuffer[n*synth->num_channels+c] = sin(synth->phase[c]) * VOLUME * 32767.0f;
    85       synth->phase[c] += phase_inc;
    86     }
    87   }
    88 }
    90 long data_cb_short(cubeb_stream *stream, void *user, void *buffer, long nframes)
    91 {
    92   synth_state *synth = (synth_state *)user;
    93   synth_run_16bit(synth, (short*)buffer, nframes);
    94   return nframes;
    95 }
    97 void state_cb(cubeb_stream *stream, void *user, cubeb_state state)
    98 {
    99 }
   101 /* Our android backends don't support float, only int16. */
   102 int supports_float32(const char* backend_id)
   103 {
   104   return (strcmp(backend_id, "opensl") != 0 &&
   105           strcmp(backend_id, "audiotrack") != 0);
   106 }
   108 /* Some backends don't have code to deal with more than mono or stereo. */
   109 int supports_channel_count(const char* backend_id, int nchannels)
   110 {
   111   return nchannels <= 2 ||
   112     (strcmp(backend_id, "opensl") != 0 && strcmp(backend_id, "audiotrack") != 0);
   113 }
   115 int run_test(int num_channels, int sampling_rate, int is_float)
   116 {
   117   int ret = CUBEB_OK;
   119   cubeb *ctx = NULL;
   120   synth_state* synth = NULL;
   121   cubeb_stream *stream = NULL;
   122   const char * backend_id = NULL;
   124   ret = cubeb_init(&ctx, "Cubeb audio test");
   125   if (ret != CUBEB_OK) {
   126     fprintf(stderr, "Error initializing cubeb library\n");
   127     goto cleanup;
   128   }
   130   backend_id = cubeb_get_backend_id(ctx);
   132   if ((is_float && !supports_float32(backend_id)) ||
   133       !supports_channel_count(backend_id, num_channels)) {
   134     /* don't treat this as a test failure. */
   135     goto cleanup;
   136   }
   138   fprintf(stderr, "Testing %d channel(s), %d Hz, %s (%s)\n", num_channels, sampling_rate, is_float ? "float" : "short", cubeb_get_backend_id(ctx));
   140   cubeb_stream_params params;
   141   params.format = is_float ? CUBEB_SAMPLE_FLOAT32NE : CUBEB_SAMPLE_S16NE;
   142   params.rate = sampling_rate;
   143   params.channels = num_channels;
   145   synth = synth_create(params.channels, params.rate);
   146   if (synth == NULL) {
   147     fprintf(stderr, "Out of memory\n");
   148     goto cleanup;
   149   }
   151   ret = cubeb_stream_init(ctx, &stream, "test tone", params,
   152                           100, is_float ? data_cb_float : data_cb_short, state_cb, synth);
   153   if (ret != CUBEB_OK) {
   154     fprintf(stderr, "Error initializing cubeb stream: %d\n", ret);
   155     goto cleanup;
   156   }
   158   cubeb_stream_start(stream);
   159   delay(200);
   160   cubeb_stream_stop(stream);
   162 cleanup:
   163   cubeb_stream_destroy(stream);
   164   cubeb_destroy(ctx);
   165   synth_destroy(synth);
   167   return ret;
   168 }
   170 int main(int argc, char *argv[])
   171 {
   172   int channel_values[] = {
   173     1,
   174     2,
   175     3,
   176     4,
   177     6,
   178   };
   180   int freq_values[] = {
   181     16000,
   182     24000,
   183     44100,
   184     48000,
   185   };
   187   for(int j = 0; j < NELEMS(channel_values); ++j) {
   188     for(int i = 0; i < NELEMS(freq_values); ++i) {
   189       assert(channel_values[j] < MAX_NUM_CHANNELS);
   190       fprintf(stderr, "--------------------------\n");
   191       assert(run_test(channel_values[j], freq_values[i], 0) == CUBEB_OK);
   192       assert(run_test(channel_values[j], freq_values[i], 1) == CUBEB_OK);
   193     }
   194   }
   196   return CUBEB_OK;
   197 }

mercurial