Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modify example code to be self-sufficient, and compile without changes #709

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

ad8e
Copy link
Contributor

@ad8e ad8e commented Jun 22, 2022

This modifies the starting example so that it will compile and run as-is. (The new user experience is discouraging when the starting example requires multiple changes and digging through documentation, and this addresses that.)

The git diff is messed up because it is embedded inside a comment. Here is a more readable diff, with explanations.

@@ -1,15 +1,26 @@
+    #include "stdio.h"
+    #include "cubeb/cubeb.h"
+    #ifdef _WIN32
+    #define WIN32_LEAN_AND_MEAN
+    #include <Windows.h>
+    #include <Objbase.h>
+    #else
+    #include <unistd.h>
+    #endif

This adds the necessary headers.

+    #define PIPE_INPUT_TO_OUTPUT true

When the user doesn't have a microphone, the starting example fails to run, with little indication of what the problem is. I added a flag which switches the behavior to output-only. Above the code, I also added a comment to explain the failure: "If you receive "Could not open the stream", you likely do not have a microphone. In that case, change PIPE_INPUT_TO_OUTPUT from true to false."

I left the input-to-output behavior as the default out of conservativeness for this patch. You can switch #define PIPE_INPUT_TO_OUTPUT true to false, to choose an output-only default. This would be more likely to run on the first try.

     long data_cb(cubeb_stream * stm, void * user,
                  const void * input_buffer, void * output_buffer, long nframes)
     {
-      const float * in  = input_buffer;
-      float * out = output_buffer;
+      const float * in = (float *)input_buffer;
+      float * out = (float *)output_buffer;

C++ doesn't allow this implicit conversion, whereas C does. This helps it compile in C++ without affecting C.

       for (int i = 0; i < nframes; ++i) {
         for (int c = 0; c < 2; ++c) {
+    #if PIPE_INPUT_TO_OUTPUT
           out[2 * i + c] = in[i];
+    #else
+          out[2 * i + c] = (float)((i * 123) % 200) / 10000.f;
+    #endif

This is the fallback I chose when the input-to-output behavior is disabled. It is a buzzy tone that doesn't sound great. I chose this one because it is simple and doesn't add state; more conventional tones like sines or sawtooth would run up against the buffer size boundary, creating a sharp jump. With this modulo tone, the sharp jumps are part of the tone, so the buffer boundaries are not noticeable.

         }
       }
       return nframes;
@@ -22,6 +33,9 @@
 
 
 int main() {
+    #if _WIN32
+      CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    #endif

COM issues were hard to diagnose and fix when I first tried cubeb a while back; this removes that problem for the new user example. The existing documentation was not in a place that is easy for new users to find quickly. I don't know about the experience now.

 	cubeb * app_ctx;
     cubeb_init(&app_ctx, "Example Application", NULL);
     int rv;
@@ -52,7 +66,11 @@
     input_params.prefs = CUBEB_STREAM_PREF_NONE;
     cubeb_stream * stm;
     rv = cubeb_stream_init(app_ctx, &stm, "Example Stream 1",
+    #if PIPE_INPUT_TO_OUTPUT
                            NULL, &input_params,
+    #else
+                             NULL, NULL,
+    #endif
                            NULL, &output_params,
                            latency_frames,
                            data_cb, state_cb,
@@ -69,7 +87,11 @@
     for (;;) {
       cubeb_stream_get_position(stm, &ts);
       printf("time=%llu\n", ts);
+    #if _WIN32
+        Sleep(1);
+    #else
       sleep(1);
+    #endif

My Windows did not have sleep(), so I used Sleep() instead.

     }
     rv = cubeb_stream_stop(stm);
     if (rv != CUBEB_OK) {
@@ -79,4 +101,3 @@
     cubeb_stream_destroy(stm);
     cubeb_destroy(app_ctx);
 }

Also, the callbacks have been shuffled to above main(), to form a single file that can be used as-is. I wrote the compilation command for g++ (msys2), and left the user to figure out Visual Studio.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant