1 /*
2 * Copyright © 2016 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. Record the mic and check there is sound. */
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 "cubeb/cubeb.h"
18 #include <atomic>
19
20 //#define ENABLE_NORMAL_LOG
21 //#define ENABLE_VERBOSE_LOG
22 #include "common.h"
23
24 #define SAMPLE_FREQUENCY 48000
25 #define STREAM_FORMAT CUBEB_SAMPLE_FLOAT32LE
26
27 struct user_state_record
28 {
29 std::atomic<int> invalid_audio_value{ 0 };
30 };
31
data_cb_record(cubeb_stream * stream,void * user,const void * inputbuffer,void * outputbuffer,long nframes)32 long data_cb_record(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
33 {
34 user_state_record * u = reinterpret_cast<user_state_record*>(user);
35 float *b = (float *)inputbuffer;
36
37 if (stream == NULL || inputbuffer == NULL || outputbuffer != NULL) {
38 return CUBEB_ERROR;
39 }
40
41 for (long i = 0; i < nframes; i++) {
42 if (b[i] <= -1.0 || b[i] >= 1.0) {
43 u->invalid_audio_value = 1;
44 break;
45 }
46 }
47
48 return nframes;
49 }
50
state_cb_record(cubeb_stream * stream,void *,cubeb_state state)51 void state_cb_record(cubeb_stream * stream, void * /*user*/, cubeb_state state)
52 {
53 if (stream == NULL)
54 return;
55
56 switch (state) {
57 case CUBEB_STATE_STARTED:
58 fprintf(stderr, "stream started\n"); break;
59 case CUBEB_STATE_STOPPED:
60 fprintf(stderr, "stream stopped\n"); break;
61 case CUBEB_STATE_DRAINED:
62 fprintf(stderr, "stream drained\n"); break;
63 default:
64 fprintf(stderr, "unknown stream state %d\n", state);
65 }
66
67 return;
68 }
69
TEST(cubeb,record)70 TEST(cubeb, record)
71 {
72 if (cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr /*print_log*/) != CUBEB_OK) {
73 fprintf(stderr, "Set log callback failed\n");
74 }
75 cubeb *ctx;
76 cubeb_stream *stream;
77 cubeb_stream_params params;
78 int r;
79 user_state_record stream_state;
80
81 r = common_init(&ctx, "Cubeb record example");
82 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb library";
83
84 std::unique_ptr<cubeb, decltype(&cubeb_destroy)>
85 cleanup_cubeb_at_exit(ctx, cubeb_destroy);
86
87 /* This test needs an available input device, skip it if this host does not
88 * have one. */
89 if (!has_available_input_device(ctx)) {
90 return;
91 }
92
93 params.format = STREAM_FORMAT;
94 params.rate = SAMPLE_FREQUENCY;
95 params.channels = 1;
96 params.layout = CUBEB_LAYOUT_UNDEFINED;
97 params.prefs = CUBEB_STREAM_PREF_NONE;
98
99 r = cubeb_stream_init(ctx, &stream, "Cubeb record (mono)", NULL, ¶ms, NULL, nullptr,
100 4096, data_cb_record, state_cb_record, &stream_state);
101 ASSERT_EQ(r, CUBEB_OK) << "Error initializing cubeb stream";
102
103 std::unique_ptr<cubeb_stream, decltype(&cubeb_stream_destroy)>
104 cleanup_stream_at_exit(stream, cubeb_stream_destroy);
105
106 cubeb_stream_start(stream);
107 delay(500);
108 cubeb_stream_stop(stream);
109
110 #ifdef __linux__
111 // user callback does not arrive in Linux, silence the error
112 fprintf(stderr, "Check is disabled in Linux\n");
113 #else
114 ASSERT_FALSE(stream_state.invalid_audio_value.load());
115 #endif
116 }
117