/src/mozilla-central/media/libcubeb/gtest/test_tone.cpp
Line | Count | Source (jump to first uncovered line) |
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 <stdio.h> |
14 | | #include <stdlib.h> |
15 | | #include <math.h> |
16 | | #include <memory> |
17 | | #include <limits.h> |
18 | | #include "cubeb/cubeb.h" |
19 | | #include "common.h" |
20 | | #include <atomic> |
21 | | |
22 | 0 | #define SAMPLE_FREQUENCY 48000 |
23 | 0 | #define STREAM_FORMAT CUBEB_SAMPLE_S16LE |
24 | | |
25 | | /* store the phase of the generated waveform */ |
26 | | struct cb_user_data { |
27 | | std::atomic<long> position; |
28 | | }; |
29 | | |
30 | | long data_cb_tone(cubeb_stream *stream, void *user, const void* /*inputbuffer*/, void *outputbuffer, long nframes) |
31 | 0 | { |
32 | 0 | struct cb_user_data *u = (struct cb_user_data *)user; |
33 | 0 | short *b = (short *)outputbuffer; |
34 | 0 | float t1, t2; |
35 | 0 | int i; |
36 | 0 |
|
37 | 0 | if (stream == NULL || u == NULL) |
38 | 0 | return CUBEB_ERROR; |
39 | 0 | |
40 | 0 | /* generate our test tone on the fly */ |
41 | 0 | for (i = 0; i < nframes; i++) { |
42 | 0 | /* North American dial tone */ |
43 | 0 | t1 = sin(2*M_PI*(i + u->position)*350/SAMPLE_FREQUENCY); |
44 | 0 | t2 = sin(2*M_PI*(i + u->position)*440/SAMPLE_FREQUENCY); |
45 | 0 | b[i] = (SHRT_MAX / 2) * t1; |
46 | 0 | b[i] += (SHRT_MAX / 2) * t2; |
47 | 0 | /* European dial tone */ |
48 | 0 | /* |
49 | 0 | t1 = sin(2*M_PI*(i + u->position)*425/SAMPLE_FREQUENCY); |
50 | 0 | b[i] = SHRT_MAX * t1; |
51 | 0 | */ |
52 | 0 | } |
53 | 0 | /* remember our phase to avoid clicking on buffer transitions */ |
54 | 0 | /* we'll still click if position overflows */ |
55 | 0 | u->position += nframes; |
56 | 0 |
|
57 | 0 | return nframes; |
58 | 0 | } |
59 | | |
60 | | void state_cb_tone(cubeb_stream *stream, void *user, cubeb_state state) |
61 | 0 | { |
62 | 0 | struct cb_user_data *u = (struct cb_user_data *)user; |
63 | 0 |
|
64 | 0 | if (stream == NULL || u == NULL) |
65 | 0 | return; |
66 | 0 | |
67 | 0 | switch (state) { |
68 | 0 | case CUBEB_STATE_STARTED: |
69 | 0 | fprintf(stderr, "stream started\n"); break; |
70 | 0 | case CUBEB_STATE_STOPPED: |
71 | 0 | fprintf(stderr, "stream stopped\n"); break; |
72 | 0 | case CUBEB_STATE_DRAINED: |
73 | 0 | fprintf(stderr, "stream drained\n"); break; |
74 | 0 | default: |
75 | 0 | fprintf(stderr, "unknown stream state %d\n", state); |
76 | 0 | } |
77 | 0 |
|
78 | 0 | return; |
79 | 0 | } |
80 | | |
81 | | TEST(cubeb, tone) |
82 | 0 | { |
83 | 0 | cubeb *ctx; |
84 | 0 | cubeb_stream *stream; |
85 | 0 | cubeb_stream_params params; |
86 | 0 | int r; |
87 | 0 |
|
88 | 0 | r = common_init(&ctx, "Cubeb tone example"); |
89 | 0 | ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library"; |
90 | 0 | |
91 | 0 | std::unique_ptr<cubeb, decltype(&cubeb_destroy)> |
92 | 0 | cleanup_cubeb_at_exit(ctx, cubeb_destroy); |
93 | 0 |
|
94 | 0 | params.format = STREAM_FORMAT; |
95 | 0 | params.rate = SAMPLE_FREQUENCY; |
96 | 0 | params.channels = 1; |
97 | 0 | params.layout = CUBEB_LAYOUT_MONO; |
98 | 0 | params.prefs = CUBEB_STREAM_PREF_NONE; |
99 | 0 |
|
100 | 0 | std::unique_ptr<cb_user_data> user_data(new cb_user_data()); |
101 | 0 | ASSERT_TRUE(!!user_data) << "Error allocating user data"; |
102 | 0 | |
103 | 0 | user_data->position = 0; |
104 | 0 |
|
105 | 0 | r = cubeb_stream_init(ctx, &stream, "Cubeb tone (mono)", NULL, NULL, NULL, ¶ms, |
106 | 0 | 4096, data_cb_tone, state_cb_tone, user_data.get()); |
107 | 0 | ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream"; |
108 | 0 | |
109 | 0 | std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)> |
110 | 0 | cleanup_stream_at_exit(stream, cubeb_stream_destroy); |
111 | 0 |
|
112 | 0 | cubeb_stream_start(stream); |
113 | 0 | delay(500); |
114 | 0 | cubeb_stream_stop(stream); |
115 | 0 |
|
116 | 0 | ASSERT_TRUE(user_data->position.load()); |
117 | 0 | } |