static int oss_write(const char *buffer, int count) { int rc; count -= count % sf_get_frame_size(oss_sf); rc = write(oss_fd, buffer, count); return rc; }
static int op_roar_buffer_space(void) { ssize_t ret; int i; int fs = sf_get_frame_size(format); for (i = 0; i < 8; i++) roar_vs_iterate(vss, ROAR_VS_NOWAIT, NULL); ret = roar_vs_get_avail_write(vss, &err); ret -= ret % fs; return ret; }
static int waveout_open(sample_format_t sf) { WAVEFORMATEX format; int rc, i; /* WAVEFORMATEX does not support channels > 2, waveOutWrite() wants little endian signed PCM */ if (sf_get_bigendian(sf) || !sf_get_signed(sf) || sf_get_channels(sf) > 2) { return -OP_ERROR_SAMPLE_FORMAT; } memset(&format, 0, sizeof(format)); format.cbSize = sizeof(format); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = sf_get_channels(sf); format.nSamplesPerSec = sf_get_rate(sf); format.wBitsPerSample = sf_get_bits(sf); format.nAvgBytesPerSec = sf_get_second_size(sf); format.nBlockAlign = sf_get_frame_size(sf); if ((rc = waveOutOpen(&wave_out, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL)) != MMSYSERR_NOERROR) { switch (rc) { case MMSYSERR_ALLOCATED: errno = EBUSY; return -OP_ERROR_ERRNO; case MMSYSERR_BADDEVICEID: case MMSYSERR_NODRIVER: errno = ENODEV; return -OP_ERROR_ERRNO; case MMSYSERR_NOMEM: errno = ENOMEM; return -OP_ERROR_ERRNO; case WAVERR_BADFORMAT: return -OP_ERROR_SAMPLE_FORMAT; } return -OP_ERROR_INTERNAL; } /* reset buffers */ for (i = 0; i < buffer_count; i++) { buffers[i].dwFlags = 0; } buffer_idx = 0; buffers_free = buffer_count; waveout_sf = sf; return 0; }
static int op_jack_buffer_space(void) { if (fail) { op_jack_exit(); return -OP_ERROR_INTERNAL; } int bytes = jack_ringbuffer_write_space(ringbuffer[0]); for (int c = 1; c < CHANNELS; c++) { int tmp = jack_ringbuffer_write_space(ringbuffer[0]); if (bytes > tmp) { bytes = tmp; } } int frames = bytes / sizeof(jack_default_audio_sample_t); int frame_size = sf_get_frame_size(sample_format); #ifdef HAVE_SAMPLERATE return (int) ((float) (frames) / resample_ratio) * frame_size; #else return frames * frame_size; #endif }
AudioObjectSetPropertyData(dev_id, &aopa, 0, NULL, layout_size, layout); if (err != noErr) d_print("Cannot set the channel layout successfully.\n"); free(layout); } static AudioStreamBasicDescription coreaudio_fill_format_description(sample_format_t sf) { AudioStreamBasicDescription desc = { .mSampleRate = (Float64)sf_get_rate(sf), .mFormatID = kAudioFormatLinearPCM, .mFormatFlags = kAudioFormatFlagIsPacked, .mBytesPerPacket = sf_get_frame_size(sf), .mFramesPerPacket = 1, .mChannelsPerFrame = sf_get_channels(sf), .mBitsPerChannel = sf_get_bits(sf), .mBytesPerFrame = sf_get_frame_size(sf), }; d_print("Bits:%d\n", sf_get_bits(sf)); if (sf_get_bigendian(sf)) desc.mFormatFlags |= kAudioFormatFlagIsBigEndian; if (sf_get_signed(sf)) desc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; return desc; }
static int op_jack_write(const char *buffer, int count) { if (fail) { op_jack_exit(); return -OP_ERROR_INTERNAL; } if (!drop_done) { return 0; } int frame_size = sf_get_frame_size(sample_format); int channels = sf_get_channels(sample_format); size_t frames = count / frame_size; /* since this is the only place where the ringbuffers get * written, available space will only grow, therefore frames_min * is safe. */ size_t frames_min = SIZE_MAX; for (int c = 0; c < CHANNELS; c++) { size_t frames_available = jack_ringbuffer_write_space(ringbuffer[c]) / sizeof(jack_default_audio_sample_t); if (frames_available < frames_min) { frames_min = frames_available; } } if (frames > frames_min) { frames = frames_min; } jack_default_audio_sample_t buf[CHANNELS][buffer_size]; /* demux and convert to float */ for (int pos = 0; pos < count; ) { int frame = pos / frame_size; for (int c = 0; c < channels; c++) { int idx = pos + c * sample_bytes; /* for now, only 2 channels and mono are supported */ if (channel_map[c] == CHANNEL_POSITION_LEFT || channel_map[c] == CHANNEL_POSITION_MONO) { buf[0][frame] = read_sample(&buffer[idx]); } else if (channel_map[c] == CHANNEL_POSITION_RIGHT || channel_map[c] == CHANNEL_POSITION_MONO) { buf[1][frame] = read_sample(&buffer[idx]); } } pos += frame_size; } #ifdef HAVE_SAMPLERATE if (resample_ratio > 1.01f || resample_ratio < 0.99) { jack_default_audio_sample_t converted[buffer_size]; SRC_DATA src_data; for (int c = 0; c < CHANNELS; c++) { src_data.data_in = buf[c]; src_data.data_out = converted; src_data.input_frames = frames; src_data.output_frames = frames_min; src_data.src_ratio = resample_ratio; src_data.end_of_input = 0; int err = src_process(src_state[c], &src_data); if (err) { d_print("libsamplerate err %s\n", src_strerror(err)); } int byte_length = src_data.output_frames_gen * sizeof(jack_default_audio_sample_t); jack_ringbuffer_write(ringbuffer[c], (const char*) converted, byte_length); } return src_data.input_frames_used * frame_size; } else { #endif int byte_length = frames * sizeof(jack_default_audio_sample_t); for (int c = 0; c < CHANNELS; c++) { jack_ringbuffer_write(ringbuffer[c], (const char*) buf[c], byte_length); } return frames * frame_size; #ifdef HAVE_SAMPLERATE } #endif }