void soundio_destroy_devices_info(SoundIoDevicesInfo *devices_info) { if (!devices_info) return; for (int i = 0; i < devices_info->input_devices.length; i += 1) soundio_device_unref(devices_info->input_devices.at(i)); for (int i = 0; i < devices_info->output_devices.length; i += 1) soundio_device_unref(devices_info->output_devices.at(i)); devices_info->input_devices.deinit(); devices_info->output_devices.deinit(); free(devices_info); }
static int init_playback_node(AudioGraph *ag) { MixerLine *master_mixer_line = ag->project->mixer_line_list.at(0); Effect *first_effect = master_mixer_line->effects.at(0); assert(first_effect->effect_type == EffectTypeSend); EffectSend *effect_send = &first_effect->effect.send; assert(effect_send->send_type == EffectSendTypeDevice); EffectSendDevice *send_device = &effect_send->send.device; SoundIoDevice *audio_device = get_device_for_id(ag, (DeviceId)send_device->device_id); if (!audio_device) { return GenesisErrorDeviceNotFound; } GenesisNodeDescriptor *playback_node_descr; int err; if ((err = genesis_audio_device_create_node_descriptor(ag->pipeline, audio_device, &playback_node_descr))) { return err; } assert(!ag->master_node); ag->master_node = ok_mem(genesis_node_descriptor_create_node(playback_node_descr)); soundio_device_unref(audio_device); return 0; }
void soundio_instream_destroy(struct SoundIoInStream *instream) { if (!instream) return; SoundIoInStreamPrivate *is = (SoundIoInStreamPrivate *)instream; SoundIo *soundio = instream->device->soundio; SoundIoPrivate *si = (SoundIoPrivate *)soundio; if (si->instream_destroy) si->instream_destroy(si, is); soundio_device_unref(instream->device); free(is); }
void soundio_outstream_destroy(SoundIoOutStream *outstream) { if (!outstream) return; SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)outstream; SoundIo *soundio = outstream->device->soundio; SoundIoPrivate *si = (SoundIoPrivate *)soundio; if (si->outstream_destroy) si->outstream_destroy(si, os); soundio_device_unref(outstream->device); free(os); }
static SoundIoDevice *get_device_for_id(AudioGraph *ag, DeviceId device_id) { assert(device_id >= 1); assert(device_id < device_id_count()); SettingsFileDeviceId *sf_device_id = &ag->settings_file->device_designations.at(device_id); if (sf_device_id->backend == SoundIoBackendNone) return genesis_get_default_output_device(ag->pipeline->context); SoundIoDevice *device = genesis_find_output_device(ag->pipeline->context, sf_device_id->backend, sf_device_id->device_id.raw(), sf_device_id->is_raw); if (device) { if (device->probe_error) { soundio_device_unref(device); return genesis_get_default_output_device(ag->pipeline->context); } return device; } return genesis_get_default_output_device(ag->pipeline->context); }
static int refresh_devices_bare(SoundIoPrivate *si) { SoundIo *soundio = &si->pub; SoundIoJack *sij = &si->backend_data.jack; if (sij->is_shutdown) return SoundIoErrorBackendDisconnected; SoundIoDevicesInfo *devices_info = allocate<SoundIoDevicesInfo>(1); if (!devices_info) return SoundIoErrorNoMem; devices_info->default_output_index = -1; devices_info->default_input_index = -1; const char **port_names = jack_get_ports(sij->client, nullptr, nullptr, 0); if (!port_names) { soundio_destroy_devices_info(devices_info); return SoundIoErrorNoMem; } SoundIoList<SoundIoJackClient> clients = {0}; const char **port_name_ptr = port_names; for (; *port_name_ptr; port_name_ptr += 1) { const char *client_and_port_name = *port_name_ptr; int client_and_port_name_len = strlen(client_and_port_name); jack_port_t *jport = jack_port_by_name(sij->client, client_and_port_name); if (!jport) { // This refresh devices scan is already outdated. Just give up and // let refresh_devices be called again. jack_free(port_names); soundio_destroy_devices_info(devices_info); return SoundIoErrorInterrupted; } int flags = jack_port_flags(jport); const char *port_type = jack_port_type(jport); if (strcmp(port_type, JACK_DEFAULT_AUDIO_TYPE) != 0) { // we don't know how to support such a port continue; } SoundIoDeviceAim aim = (flags & JackPortIsInput) ? SoundIoDeviceAimOutput : SoundIoDeviceAimInput; bool is_physical = flags & JackPortIsPhysical; const char *client_name = nullptr; const char *port_name = nullptr; int client_name_len; int port_name_len; split_str(client_and_port_name, client_and_port_name_len, ':', &client_name, &client_name_len, &port_name, &port_name_len); if (!client_name || !port_name) { // device does not have colon, skip it continue; } SoundIoJackClient *client = find_or_create_client(&clients, aim, is_physical, client_name, client_name_len); if (!client) { jack_free(port_names); soundio_destroy_devices_info(devices_info); return SoundIoErrorNoMem; } if (client->port_count >= SOUNDIO_MAX_CHANNELS) { // we hit the channel limit, skip the leftovers continue; } SoundIoJackPort *port = &client->ports[client->port_count++]; port->full_name = client_and_port_name; port->full_name_len = client_and_port_name_len; port->name = port_name; port->name_len = port_name_len; port->channel_id = soundio_parse_channel_id(port_name, port_name_len); jack_latency_callback_mode_t latency_mode = (aim == SoundIoDeviceAimOutput) ? JackPlaybackLatency : JackCaptureLatency; jack_port_get_latency_range(jport, latency_mode, &port->latency_range); } for (int i = 0; i < clients.length; i += 1) { SoundIoJackClient *client = &clients.at(i); if (client->port_count <= 0) continue; SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1); if (!dev) { jack_free(port_names); soundio_destroy_devices_info(devices_info); return SoundIoErrorNoMem; } SoundIoDevice *device = &dev->pub; SoundIoDeviceJack *dj = &dev->backend_data.jack; int description_len = client->name_len + 3 + 2 * client->port_count; for (int port_index = 0; port_index < client->port_count; port_index += 1) { SoundIoJackPort *port = &client->ports[port_index]; description_len += port->name_len; } dev->destruct = destruct_device; device->ref_count = 1; device->soundio = soundio; device->is_raw = false; device->aim = client->aim; device->id = soundio_str_dupe(client->name, client->name_len); device->name = allocate<char>(description_len); device->current_format = SoundIoFormatFloat32NE; device->sample_rate_count = 1; device->sample_rates = &dev->prealloc_sample_rate_range; device->sample_rates[0].min = sij->sample_rate; device->sample_rates[0].max = sij->sample_rate; device->sample_rate_current = sij->sample_rate; device->software_latency_current = sij->period_size / (double) sij->sample_rate; device->software_latency_min = sij->period_size / (double) sij->sample_rate; device->software_latency_max = sij->period_size / (double) sij->sample_rate; dj->port_count = client->port_count; dj->ports = allocate<SoundIoDeviceJackPort>(dj->port_count); if (!device->id || !device->name || !dj->ports) { jack_free(port_names); soundio_device_unref(device); soundio_destroy_devices_info(devices_info); return SoundIoErrorNoMem; } for (int port_index = 0; port_index < client->port_count; port_index += 1) { SoundIoJackPort *port = &client->ports[port_index]; SoundIoDeviceJackPort *djp = &dj->ports[port_index]; djp->full_name = soundio_str_dupe(port->full_name, port->full_name_len); djp->full_name_len = port->full_name_len; djp->channel_id = port->channel_id; djp->latency_range = port->latency_range; if (!djp->full_name) { jack_free(port_names); soundio_device_unref(device); soundio_destroy_devices_info(devices_info); return SoundIoErrorNoMem; } } memcpy(device->name, client->name, client->name_len); memcpy(&device->name[client->name_len], ": ", 2); int index = client->name_len + 2; for (int port_index = 0; port_index < client->port_count; port_index += 1) { SoundIoJackPort *port = &client->ports[port_index]; memcpy(&device->name[index], port->name, port->name_len); index += port->name_len; if (port_index + 1 < client->port_count) { memcpy(&device->name[index], ", ", 2); index += 2; } } device->current_layout.channel_count = client->port_count; bool any_invalid = false; for (int port_index = 0; port_index < client->port_count; port_index += 1) { SoundIoJackPort *port = &client->ports[port_index]; device->current_layout.channels[port_index] = port->channel_id; any_invalid = any_invalid || (port->channel_id == SoundIoChannelIdInvalid); } if (any_invalid) { const struct SoundIoChannelLayout *layout = soundio_channel_layout_get_default(client->port_count); if (layout) device->current_layout = *layout; } else { soundio_channel_layout_detect_builtin(&device->current_layout); } device->layout_count = 1; device->layouts = &device->current_layout; device->format_count = 1; device->formats = &dev->prealloc_format; device->formats[0] = device->current_format; SoundIoList<SoundIoDevice *> *device_list; if (device->aim == SoundIoDeviceAimOutput) { device_list = &devices_info->output_devices; if (devices_info->default_output_index < 0 && client->is_physical) devices_info->default_output_index = device_list->length; } else { assert(device->aim == SoundIoDeviceAimInput); device_list = &devices_info->input_devices; if (devices_info->default_input_index < 0 && client->is_physical) devices_info->default_input_index = device_list->length; } if (device_list->append(device)) { soundio_device_unref(device); soundio_destroy_devices_info(devices_info); return SoundIoErrorNoMem; } } jack_free(port_names); soundio_destroy_devices_info(si->safe_devices_info); si->safe_devices_info = devices_info; return 0; }
AudioSoundIo::AudioSoundIo( bool & outSuccessful, Mixer * _mixer ) : AudioDevice( tLimit<ch_cnt_t>( ConfigManager::inst()->value( "audiosoundio", "channels" ).toInt(), DEFAULT_CHANNELS, SURROUND_CHANNELS ), _mixer ) { outSuccessful = false; m_soundio = NULL; m_outstream = NULL; m_disconnectErr = 0; m_outBufFrameIndex = 0; m_outBufFramesTotal = 0; m_soundio = soundio_create(); if (!m_soundio) { fprintf(stderr, "Unable to initialize soundio: out of memory\n"); return; } m_soundio->app_name = "LMMS"; m_soundio->userdata = this; m_soundio->on_backend_disconnect = staticOnBackendDisconnect; const QString& configBackend = ConfigManager::inst()->value( "audiosoundio", "backend" ); const QString& configDeviceId = ConfigManager::inst()->value( "audiosoundio", "out_device_id" ); const QString& configDeviceRaw = ConfigManager::inst()->value( "audiosoundio", "out_device_raw" ); int err; int outDeviceCount = 0; int backendCount = soundio_backend_count(m_soundio); for (int i = 0; i < backendCount; i += 1) { SoundIoBackend backend = soundio_get_backend(m_soundio, i); if (configBackend == soundio_backend_name(backend)) { if ((err = soundio_connect_backend(m_soundio, backend))) { // error occurred, leave outDeviceCount 0 } else { soundio_flush_events(m_soundio); if (m_disconnectErr) { fprintf(stderr, "Unable to initialize soundio: %s\n", soundio_strerror(m_disconnectErr)); return; } outDeviceCount = soundio_output_device_count(m_soundio); } break; } } if (outDeviceCount <= 0) { // try connecting to the default backend if ((err = soundio_connect(m_soundio))) { fprintf(stderr, "Unable to initialize soundio: %s\n", soundio_strerror(err)); return; } soundio_flush_events(m_soundio); if (m_disconnectErr) { fprintf(stderr, "Unable to initialize soundio: %s\n", soundio_strerror(m_disconnectErr)); return; } outDeviceCount = soundio_output_device_count(m_soundio); if (outDeviceCount <= 0) { fprintf(stderr, "Unable to initialize soundio: no devices found\n"); return; } } int selected_device_index = soundio_default_output_device_index(m_soundio); bool wantRaw = (configDeviceRaw == "yes"); for (int i = 0; i < outDeviceCount; i += 1) { SoundIoDevice *device = soundio_get_output_device(m_soundio, i); bool isThisOne = (configDeviceId == device->id && wantRaw == device->is_raw); soundio_device_unref(device); if (isThisOne) { selected_device_index = i; break; } } SoundIoDevice *device = soundio_get_output_device(m_soundio, selected_device_index); m_outstream = soundio_outstream_create(device); soundio_device_unref(device); if (!m_outstream) { fprintf(stderr, "Unable to initialize soundio: out of memory\n"); return; } int currentSampleRate = sampleRate(); int closestSupportedSampleRate = -1; for (int i = 0; i < device->sample_rate_count; i += 1) { SoundIoSampleRateRange *range = &device->sample_rates[i]; if (range->min <= currentSampleRate && currentSampleRate <= range->max) { closestSupportedSampleRate = currentSampleRate; break; } if (closestSupportedSampleRate == -1 || abs(range->max - currentSampleRate) < abs(closestSupportedSampleRate - currentSampleRate)) { closestSupportedSampleRate = range->max; } } if (closestSupportedSampleRate != currentSampleRate) { setSampleRate(closestSupportedSampleRate); currentSampleRate = closestSupportedSampleRate; } m_outstream->name = "LMMS"; m_outstream->software_latency = (double)mixer()->framesPerPeriod() / (double)currentSampleRate; m_outstream->userdata = this; m_outstream->write_callback = staticWriteCallback; m_outstream->error_callback = staticErrorCallback; m_outstream->underflow_callback = staticUnderflowCallback; m_outstream->sample_rate = currentSampleRate; m_outstream->layout = *soundio_channel_layout_get_default(channels()); m_outstream->format = SoundIoFormatFloat32NE; if ((err = soundio_outstream_open(m_outstream))) { fprintf(stderr, "Unable to initialize soundio: %s\n", soundio_strerror(err)); return; } fprintf(stderr, "Output device: '%s' backend: '%s'\n", device->name, soundio_backend_name(m_soundio->current_backend)); outSuccessful = true; }
static void source_info_callback(pa_context *pulse_context, const pa_source_info *info, int eol, void *userdata) { struct SoundIoPrivate *si = (struct SoundIoPrivate *)userdata; struct SoundIo *soundio = &si->pub; struct SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; int err; if (eol) { pa_threaded_mainloop_signal(sipa->main_loop, 0); return; } if (sipa->device_query_err) return; struct SoundIoDevicePrivate *dev = ALLOCATE(struct SoundIoDevicePrivate, 1); if (!dev) { sipa->device_query_err = SoundIoErrorNoMem; return; } struct SoundIoDevice *device = &dev->pub; device->ref_count = 1; device->soundio = soundio; device->id = strdup(info->name); device->name = strdup(info->description); if (!device->id || !device->name) { soundio_device_unref(device); sipa->device_query_err = SoundIoErrorNoMem; return; } device->sample_rate_current = info->sample_spec.rate; // PulseAudio performs resampling, so any value is valid. Let's pick // some reasonable min and max values. device->sample_rate_count = 1; device->sample_rates = &dev->prealloc_sample_rate_range; device->sample_rates[0].min = soundio_int_min(SOUNDIO_MIN_SAMPLE_RATE, device->sample_rate_current); device->sample_rates[0].max = soundio_int_max(SOUNDIO_MAX_SAMPLE_RATE, device->sample_rate_current); device->current_format = from_pulseaudio_format(info->sample_spec); // PulseAudio performs sample format conversion, so any PulseAudio // value is valid. if ((err = set_all_device_formats(device))) { soundio_device_unref(device); sipa->device_query_err = SoundIoErrorNoMem; return; } set_from_pulseaudio_channel_map(info->channel_map, &device->current_layout); // PulseAudio does channel layout remapping, so any channel layout is valid. if ((err = set_all_device_channel_layouts(device))) { soundio_device_unref(device); sipa->device_query_err = SoundIoErrorNoMem; return; } device->aim = SoundIoDeviceAimInput; if (SoundIoListDevicePtr_append(&sipa->current_devices_info->input_devices, device)) { soundio_device_unref(device); sipa->device_query_err = SoundIoErrorNoMem; return; } }
int main(int argc, char **argv) { char *exe = argv[0]; enum SoundIoBackend backend = SoundIoBackendNone; bool is_raw = false; char *device_id = NULL; for (int i = 1; i < argc; i += 1) { char *arg = argv[i]; if (arg[0] == '-' && arg[1] == '-') { if (strcmp(arg, "--raw") == 0) { is_raw = true; } else if (++i >= argc) { return usage(exe); } else if (strcmp(arg, "--device") == 0) { device_id = argv[i]; } else if (strcmp(arg, "--backend") == 0) { if (strcmp("dummy", argv[i]) == 0) { backend = SoundIoBackendDummy; } else if (strcmp("alsa", argv[i]) == 0) { backend = SoundIoBackendAlsa; } else if (strcmp("pulseaudio", argv[i]) == 0) { backend = SoundIoBackendPulseAudio; } else if (strcmp("jack", argv[i]) == 0) { backend = SoundIoBackendJack; } else if (strcmp("coreaudio", argv[i]) == 0) { backend = SoundIoBackendCoreAudio; } else if (strcmp("wasapi", argv[i]) == 0) { backend = SoundIoBackendWasapi; } else { fprintf(stderr, "Invalid backend: %s\n", argv[i]); return 1; } } else { return usage(exe); } } else { return usage(exe); } } fprintf(stderr, "Records for 3 seconds, sleeps for 3 seconds, then you should see at least\n" "one buffer overflow message, then records for 3 seconds.\n" "PulseAudio is not expected to pass this test.\n" "CoreAudio is not expected to pass this test.\n" "WASAPI is not expected to pass this test.\n"); if (!(soundio = soundio_create())) panic("out of memory"); int err = (backend == SoundIoBackendNone) ? soundio_connect(soundio) : soundio_connect_backend(soundio, backend); if (err) panic("error connecting: %s", soundio_strerror(err)); soundio_flush_events(soundio); int selected_device_index = -1; if (device_id) { int device_count = soundio_input_device_count(soundio); for (int i = 0; i < device_count; i += 1) { struct SoundIoDevice *device = soundio_get_input_device(soundio, i); if (strcmp(device->id, device_id) == 0 && device->is_raw == is_raw) { selected_device_index = i; break; } } } else { selected_device_index = soundio_default_input_device_index(soundio); } if (selected_device_index < 0) { fprintf(stderr, "input device not found\n"); return 1; } struct SoundIoDevice *device = soundio_get_input_device(soundio, selected_device_index); if (!device) { fprintf(stderr, "out of memory\n"); return 1; } fprintf(stderr, "Input device: %s\n", device->name); enum SoundIoFormat *fmt; for (fmt = prioritized_formats; *fmt != SoundIoFormatInvalid; fmt += 1) { if (soundio_device_supports_format(device, *fmt)) break; } if (*fmt == SoundIoFormatInvalid) panic("incompatible sample format"); struct SoundIoInStream *instream = soundio_instream_create(device); instream->format = *fmt; instream->read_callback = read_callback; instream->overflow_callback = overflow_callback; if ((err = soundio_instream_open(instream))) panic("unable to open device: %s", soundio_strerror(err)); fprintf(stderr, "OK format: %s\n", soundio_format_string(instream->format)); if ((err = soundio_instream_start(instream))) panic("unable to start device: %s", soundio_strerror(err)); while (seconds_offset < seconds_end) soundio_wait_events(soundio); soundio_instream_destroy(instream); soundio_device_unref(device); soundio_destroy(soundio); if (overflow_count > 0) { fprintf(stderr, "OK test passed with %d overflow callbacks\n", overflow_count); return 0; } else { fprintf(stderr, "FAIL no overflow callbacks received\n"); return 1; } }
//============================================================================== // MAIN //============================================================================== int main(int argc,char **argv) { pthread_t test; printf("SFemtoZ!\n"); int c; while ((c = getopt (argc, argv, "t:v")) != -1) switch (c) { case 't': if(pthread_create(&test,NULL,thread_test,optarg)) { printf("error thread test\n"); } break; case 'v': verbose=TRUE; break; } char sfzfile[50]; strcpy(sfzfile,USBPATH); strcat(sfzfile,argv[optind]); printf("Load SFZ: %s\n",sfzfile); loadsfz(sfzfile); //printsfz(); loadsounds(); int fd; if(( fd = serialOpen("/dev/ttyAMA0",57600))<0) { printf("serialOpen ERROR:\n",strerror(errno)); return 1; } if(configuresoundio()!=0) return 1; signal(SIGINT,exit_cli); signal(SIGTERM,exit_cli); run = TRUE; while(run) { if(serialDataAvail(fd)>2) { int type=serialGetchar(fd); while(type!=0x99 && type!= 0xB9) type=serialGetchar(fd); int note=serialGetchar(fd); int vel=serialGetchar(fd); //printf("MIDI%i(%i,%i)\n",type,note,vel); if(type==0x99) noteOn(note,vel); else midiCC(note,vel); } // soundio_wait_events(soundio); } //FINISH pthread_cancel(test); soundio_outstream_destroy(outstream); soundio_device_unref(device); soundio_destroy(soundio); serialClose(fd); freesounds(); freesfz(); return 0; }
int main(int argc, char **argv) { char *exe = argv[0]; enum SoundIoBackend backend = SoundIoBackendNone; char *device_id = NULL; bool raw = false; char *stream_name = NULL; double latency = 0.0; int sample_rate = 0; for (int i = 1; i < argc; i += 1) { char *arg = argv[i]; if (arg[0] == '-' && arg[1] == '-') { if (strcmp(arg, "--raw") == 0) { raw = true; } else { i += 1; if (i >= argc) { return usage(exe); } else if (strcmp(arg, "--backend") == 0) { if (strcmp(argv[i], "dummy") == 0) { backend = SoundIoBackendDummy; } else if (strcmp(argv[i], "alsa") == 0) { backend = SoundIoBackendAlsa; } else if (strcmp(argv[i], "pulseaudio") == 0) { backend = SoundIoBackendPulseAudio; } else if (strcmp(argv[i], "jack") == 0) { backend = SoundIoBackendJack; } else if (strcmp(argv[i], "coreaudio") == 0) { backend = SoundIoBackendCoreAudio; } else if (strcmp(argv[i], "wasapi") == 0) { backend = SoundIoBackendWasapi; } else { fprintf(stderr, "Invalid backend: %s\n", argv[i]); return 1; } } else if (strcmp(arg, "--device") == 0) { device_id = argv[i]; } else if (strcmp(arg, "--name") == 0) { stream_name = argv[i]; } else if (strcmp(arg, "--latency") == 0) { latency = atof(argv[i]); } else if (strcmp(arg, "--sample-rate") == 0) { sample_rate = atoi(argv[i]); } else { return usage(exe); } } } else { return usage(exe); } } struct SoundIo *soundio = soundio_create(); if (!soundio) { fprintf(stderr, "out of memory\n"); return 1; } int err = (backend == SoundIoBackendNone) ? soundio_connect(soundio) : soundio_connect_backend(soundio, backend); if (err) { fprintf(stderr, "Unable to connect to backend: %s\n", soundio_strerror(err)); return 1; } fprintf(stderr, "Backend: %s\n", soundio_backend_name(soundio->current_backend)); soundio_flush_events(soundio); int selected_device_index = -1; if (device_id) { int device_count = soundio_output_device_count(soundio); for (int i = 0; i < device_count; i += 1) { struct SoundIoDevice *device = soundio_get_output_device(soundio, i); bool select_this_one = strcmp(device->id, device_id) == 0 && device->is_raw == raw; soundio_device_unref(device); if (select_this_one) { selected_device_index = i; break; } } } else { selected_device_index = soundio_default_output_device_index(soundio); } if (selected_device_index < 0) { fprintf(stderr, "Output device not found\n"); return 1; } struct SoundIoDevice *device = soundio_get_output_device(soundio, selected_device_index); if (!device) { fprintf(stderr, "out of memory\n"); return 1; } fprintf(stderr, "Output device: %s\n", device->name); if (device->probe_error) { fprintf(stderr, "Cannot probe device: %s\n", soundio_strerror(device->probe_error)); return 1; } struct SoundIoOutStream *outstream = soundio_outstream_create(device); if (!outstream) { fprintf(stderr, "out of memory\n"); return 1; } outstream->write_callback = write_callback; outstream->underflow_callback = underflow_callback; outstream->name = stream_name; outstream->software_latency = latency; outstream->sample_rate = sample_rate; if (soundio_device_supports_format(device, SoundIoFormatFloat32NE)) { outstream->format = SoundIoFormatFloat32NE; write_sample = write_sample_float32ne; } else if (soundio_device_supports_format(device, SoundIoFormatFloat64NE)) { outstream->format = SoundIoFormatFloat64NE; write_sample = write_sample_float64ne; } else if (soundio_device_supports_format(device, SoundIoFormatS32NE)) { outstream->format = SoundIoFormatS32NE; write_sample = write_sample_s32ne; } else if (soundio_device_supports_format(device, SoundIoFormatS16NE)) { outstream->format = SoundIoFormatS16NE; write_sample = write_sample_s16ne; } else { fprintf(stderr, "No suitable device format available.\n"); return 1; } if ((err = soundio_outstream_open(outstream))) { fprintf(stderr, "unable to open device: %s", soundio_strerror(err)); return 1; } fprintf(stderr, "Software latency: %f\n", outstream->software_latency); fprintf(stderr, "'p\\n' - pause\n" "'u\\n' - unpause\n" "'P\\n' - pause from within callback\n" "'c\\n' - clear buffer\n" "'q\\n' - quit\n"); if (outstream->layout_error) fprintf(stderr, "unable to set channel layout: %s\n", soundio_strerror(outstream->layout_error)); if ((err = soundio_outstream_start(outstream))) { fprintf(stderr, "unable to start device: %s\n", soundio_strerror(err)); return 1; } for (;;) { soundio_flush_events(soundio); int c = getc(stdin); if (c == 'p') { fprintf(stderr, "pausing result: %s\n", soundio_strerror(soundio_outstream_pause(outstream, true))); } else if (c == 'P') { want_pause = true; } else if (c == 'u') { want_pause = false; fprintf(stderr, "unpausing result: %s\n", soundio_strerror(soundio_outstream_pause(outstream, false))); } else if (c == 'c') { fprintf(stderr, "clear buffer result: %s\n", soundio_strerror(soundio_outstream_clear_buffer(outstream))); } else if (c == 'q') { break; } else if (c == '\r' || c == '\n') { // ignore } else { fprintf(stderr, "Unrecognized command: %c\n", c); } } soundio_outstream_destroy(outstream); soundio_device_unref(device); soundio_destroy(soundio); return 0; }