mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Initial working implementation of full-duplex on WASAPI.
This commit is contained in:
+45
-79
@@ -1,106 +1,72 @@
|
||||
// This example simply captures data from your default microphone until you press Enter, after
|
||||
// which it plays back the captured audio.
|
||||
// This example simply captures data from your default microphone until you press Enter. The output is saved to the file specified on the command line.
|
||||
|
||||
#define MINI_AL_IMPLEMENTATION
|
||||
#include "../mini_al.h"
|
||||
|
||||
#define DR_WAV_IMPLEMENTATION
|
||||
#include "../extras/dr_wav.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
mal_uint32 capturedSampleCount = 0;
|
||||
mal_int16* pCapturedSamples = NULL;
|
||||
mal_uint32 playbackSample = 0;
|
||||
|
||||
void on_recv_frames(mal_device* pDevice, void* pOutput, const void* pInput, mal_uint32 frameCount)
|
||||
void data_callback(mal_device* pDevice, void* pOutput, const void* pInput, mal_uint32 frameCount)
|
||||
{
|
||||
mal_uint32 sampleCount = frameCount * pDevice->channels;
|
||||
|
||||
mal_uint32 newCapturedSampleCount = capturedSampleCount + sampleCount;
|
||||
mal_int16* pNewCapturedSamples = (mal_int16*)realloc(pCapturedSamples, newCapturedSampleCount * sizeof(mal_int16));
|
||||
if (pNewCapturedSamples == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(pNewCapturedSamples + capturedSampleCount, pInput, sampleCount * sizeof(mal_int16));
|
||||
|
||||
pCapturedSamples = pNewCapturedSamples;
|
||||
capturedSampleCount = newCapturedSampleCount;
|
||||
|
||||
(void)pOutput;
|
||||
|
||||
drwav* pWav = (drwav*)pDevice->pUserData;
|
||||
mal_assert(pWav != NULL);
|
||||
|
||||
drwav_write_pcm_frames(pWav, frameCount, pInput);
|
||||
}
|
||||
|
||||
void on_send_frames(mal_device* pDevice, void* pOutput, const void* pInput, mal_uint32 frameCount)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
mal_uint32 samplesToRead = frameCount * pDevice->channels;
|
||||
if (samplesToRead > capturedSampleCount-playbackSample) {
|
||||
samplesToRead = capturedSampleCount-playbackSample;
|
||||
}
|
||||
|
||||
if (samplesToRead == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(pOutput, pCapturedSamples + playbackSample, samplesToRead * sizeof(mal_int16));
|
||||
playbackSample += samplesToRead;
|
||||
|
||||
(void)pInput;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
mal_device_config config;
|
||||
|
||||
mal_context context;
|
||||
if (mal_context_init(NULL, 0, NULL, &context) != MAL_SUCCESS) {
|
||||
printf("Failed to initialize context.");
|
||||
if (argc < 2) {
|
||||
printf("No input file.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Recording...\n");
|
||||
config = mal_device_config_init(mal_format_s16, 2, 48000, on_recv_frames, NULL);
|
||||
mal_device captureDevice;
|
||||
if (mal_device_init(&context, mal_device_type_capture, NULL, &config, &captureDevice) != MAL_SUCCESS) {
|
||||
mal_context_uninit(&context);
|
||||
mal_result result;
|
||||
|
||||
drwav_data_format wavFormat;
|
||||
wavFormat.container = drwav_container_riff;
|
||||
wavFormat.format = DR_WAVE_FORMAT_IEEE_FLOAT;
|
||||
wavFormat.channels = 2;
|
||||
wavFormat.sampleRate = 44100;
|
||||
wavFormat.bitsPerSample = 32;
|
||||
|
||||
drwav wav;
|
||||
if (drwav_init_file_write(&wav, argv[1], &wavFormat) == DRWAV_FALSE) {
|
||||
printf("Failed to initialize output file.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mal_device_config config = mal_device_config_init(mal_device_type_capture);
|
||||
config.capture.format = mal_format_f32;
|
||||
config.capture.channels = wavFormat.channels;
|
||||
config.sampleRate = wavFormat.sampleRate;
|
||||
config.dataCallback = data_callback;
|
||||
config.pUserData = &wav;
|
||||
|
||||
mal_device device;
|
||||
result = mal_device_init(NULL, &config, &device);
|
||||
if (result != MAL_SUCCESS) {
|
||||
printf("Failed to initialize capture device.\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (mal_device_start(&captureDevice) != MAL_SUCCESS) {
|
||||
mal_device_uninit(&captureDevice);
|
||||
mal_context_uninit(&context);
|
||||
printf("Failed to start capture device.\n");
|
||||
result = mal_device_start(&device);
|
||||
if (result != MAL_SUCCESS) {
|
||||
mal_device_uninit(&device);
|
||||
printf("Failed to start device.\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
printf("Press Enter to stop recording...\n");
|
||||
getchar();
|
||||
|
||||
mal_device_uninit(&device);
|
||||
drwav_uninit(&wav);
|
||||
|
||||
mal_device_uninit(&captureDevice);
|
||||
|
||||
|
||||
|
||||
printf("Playing...\n");
|
||||
config = mal_device_config_init(mal_format_s16, 2, 48000, on_send_frames, NULL);
|
||||
mal_device playbackDevice;
|
||||
if (mal_device_init(&context, mal_device_type_playback, NULL, &config, &playbackDevice) != MAL_SUCCESS) {
|
||||
mal_context_uninit(&context);
|
||||
printf("Failed to initialize playback device.\n");
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (mal_device_start(&playbackDevice) != MAL_SUCCESS) {
|
||||
mal_device_uninit(&playbackDevice);
|
||||
mal_context_uninit(&context);
|
||||
printf("Failed to start playback device.\n");
|
||||
return -5;
|
||||
}
|
||||
|
||||
printf("Press Enter to quit...\n");
|
||||
getchar();
|
||||
|
||||
mal_device_uninit(&playbackDevice);
|
||||
|
||||
mal_context_uninit(&context);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user