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, &params, 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