// coop_tone: a minimal WASAPI render process that plays a continuous sine wave on the // default output endpoint, at a configurable audio format. Used as a known audio source // for the audio-mirror tests (a real process actively rendering audio to capture from). // // coop_tone [seconds] [frequencyHz] [rate] [channels] [bits] [float|pcm] // // Each trailing arg is optional; an omitted format field uses the device mix format. // Default: ~3 s, 440 Hz, device format. Prints "TONE_RENDERING" once audio is flowing so // a parent can synchronize before it starts capturing. #include #include #include #include #include "tone_source.hpp" int wmain(int argc, wchar_t** argv) { const double seconds = (argc > 1) ? _wtof(argv[1]) : 3.0; const double freq = (argc > 2) ? _wtof(argv[2]) : 440.0; coop::tone::ToneFormat tf; if (argc > 3) { tf.rate = static_cast(_wtoi(argv[3])); } if (argc > 4) { tf.channels = static_cast(_wtoi(argv[4])); } if (argc > 5) { tf.bits = static_cast(_wtoi(argv[5])); } tf.is_float = (argc > 6) ? (_wcsicmp(argv[6], L"float") == 0) : (tf.bits == 32); // 32-bit -> float default if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) { std::fprintf(stderr, "CoInitializeEx failed\n"); return 1; } int rc = 1; coop::tone::ToneSource tone; if (tone.open(tf, freq)) { const coop::tone::ToneFormat& f = tone.format(); std::printf("TONE_RENDERING pid=%lu %.0fHz %uHz %uch %ubit %s\n", GetCurrentProcessId(), freq, f.rate, f.channels, f.bits, f.is_float ? "float" : "pcm"); std::fflush(stdout); const DWORD end_tick = GetTickCount() + static_cast(seconds * 1000.0); while (GetTickCount() < end_tick) { tone.render_step(200); } tone.close(); rc = 0; } else { std::fprintf(stderr, "TONE_OPEN_FAILED (endpoint or format unavailable)\n"); } CoUninitialize(); return rc; }