test_tone.cpp (3332B)
1 /* 2 * Copyright © 2011 Mozilla Foundation 3 * 4 * This program is made available under an ISC-style license. See the 5 * accompanying file LICENSE for details. 6 */ 7 8 /* libcubeb api/function test. Plays a simple tone. */ 9 #include "gtest/gtest.h" 10 #if !defined(_XOPEN_SOURCE) 11 #define _XOPEN_SOURCE 600 12 #endif 13 #include "cubeb/cubeb.h" 14 #include <atomic> 15 #include <limits.h> 16 #include <math.h> 17 #include <memory> 18 #include <stdio.h> 19 #include <stdlib.h> 20 21 // #define ENABLE_NORMAL_LOG 22 // #define ENABLE_VERBOSE_LOG 23 #include "common.h" 24 25 #define SAMPLE_FREQUENCY 48000 26 #define STREAM_FORMAT CUBEB_SAMPLE_S16LE 27 28 /* store the phase of the generated waveform */ 29 struct cb_user_data { 30 std::atomic<long> position; 31 }; 32 33 long 34 data_cb_tone(cubeb_stream * stream, void * user, const void * /*inputbuffer*/, 35 void * outputbuffer, long nframes) 36 { 37 struct cb_user_data * u = (struct cb_user_data *)user; 38 short * b = (short *)outputbuffer; 39 float t1, t2; 40 int i; 41 42 if (stream == NULL || u == NULL) 43 return CUBEB_ERROR; 44 45 /* generate our test tone on the fly */ 46 for (i = 0; i < nframes; i++) { 47 /* North American dial tone */ 48 t1 = sin(2 * M_PI * (i + u->position) * 350 / SAMPLE_FREQUENCY); 49 t2 = sin(2 * M_PI * (i + u->position) * 440 / SAMPLE_FREQUENCY); 50 b[i] = (SHRT_MAX / 2) * t1; 51 b[i] += (SHRT_MAX / 2) * t2; 52 /* European dial tone */ 53 /* 54 t1 = sin(2*M_PI*(i + u->position)*425/SAMPLE_FREQUENCY); 55 b[i] = SHRT_MAX * t1; 56 */ 57 } 58 /* remember our phase to avoid clicking on buffer transitions */ 59 /* we'll still click if position overflows */ 60 u->position += nframes; 61 62 return nframes; 63 } 64 65 void 66 state_cb_tone(cubeb_stream * stream, void * user, cubeb_state state) 67 { 68 struct cb_user_data * u = (struct cb_user_data *)user; 69 70 if (stream == NULL || u == NULL) 71 return; 72 73 switch (state) { 74 case CUBEB_STATE_STARTED: 75 fprintf(stderr, "stream started\n"); 76 break; 77 case CUBEB_STATE_STOPPED: 78 fprintf(stderr, "stream stopped\n"); 79 break; 80 case CUBEB_STATE_DRAINED: 81 fprintf(stderr, "stream drained\n"); 82 break; 83 default: 84 fprintf(stderr, "unknown stream state %d\n", state); 85 } 86 87 return; 88 } 89 90 TEST(cubeb, tone) 91 { 92 cubeb * ctx; 93 cubeb_stream * stream; 94 cubeb_stream_params params; 95 int r; 96 97 r = common_init(&ctx, "Cubeb tone example"); 98 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; 99 100 std::unique_ptr<cubeb, decltype(&cubeb_destroy)> cleanup_cubeb_at_exit( 101 ctx, cubeb_destroy); 102 103 params.format = STREAM_FORMAT; 104 params.rate = SAMPLE_FREQUENCY; 105 params.channels = 1; 106 params.layout = CUBEB_LAYOUT_MONO; 107 params.prefs = CUBEB_STREAM_PREF_NONE; 108 109 std::unique_ptr<cb_user_data> user_data(new cb_user_data()); 110 ASSERT_TRUE(!!user_data) << "Error allocating user data"; 111 112 user_data->position = 0; 113 114 r = cubeb_stream_init(ctx, &stream, "Cubeb tone (mono)", NULL, NULL, NULL, 115 ¶ms, 4096, data_cb_tone, state_cb_tone, 116 user_data.get()); 117 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream"; 118 119 std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)> 120 cleanup_stream_at_exit(stream, cubeb_stream_destroy); 121 122 cubeb_stream_start(stream); 123 delay(5000); 124 cubeb_stream_stop(stream); 125 126 ASSERT_TRUE(user_data->position.load()); 127 } 128 129 #undef SAMPLE_FREQUENCY 130 #undef STREAM_FORMAT