static inline int sf_need_swap(sample_format_t sf) { #ifdef WORDS_BIGENDIAN return !sf_get_bigendian(sf); #else return sf_get_bigendian(sf); #endif }
static int sndio_set_sf(sample_format_t sf) { struct sio_par apar; sndio_sf = sf; sio_initpar(&par); par.pchan = sf_get_channels(sndio_sf); par.rate = sf_get_rate(sndio_sf); sndio_paused = 0; if (sf_get_signed(sndio_sf)) par.sig = 1; else par.sig = 0; if (sf_get_bigendian(sndio_sf)) par.le = 0; else par.le = 1; switch (sf_get_bits(sndio_sf)) { case 16: par.bits = 16; break; case 8: par.bits = 8; break; default: return -OP_ERROR_SAMPLE_FORMAT; } par.appbufsz = par.rate * 300 / 1000; apar = par; if (!sio_setpar(hdl, &par)) return -OP_ERROR_INTERNAL; if (!sio_getpar(hdl, &par)) return -OP_ERROR_INTERNAL; if (apar.rate != par.rate || apar.pchan != par.pchan || apar.bits != par.bits || (par.bits > 8 && apar.le != par.le) || apar.sig != par.sig) return -OP_ERROR_INTERNAL; sndio_mixer_set_volume(sndio_volume, sndio_volume); if (!sio_start(hdl)) return -OP_ERROR_INTERNAL; return OP_ERROR_SUCCESS; }
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 void scale_samples(char *buffer, unsigned int *countp) { unsigned int count = *countp; int ch, bits, l, r; BUG_ON(scale_pos < consumer_pos); if (consumer_pos != scale_pos) { unsigned int offs = scale_pos - consumer_pos; if (offs >= count) return; buffer += offs; count -= offs; } scale_pos += count; if (replaygain_scale == 1.0 && soft_vol_l == 100 && soft_vol_r == 100) return; ch = sf_get_channels(buffer_sf); bits = sf_get_bits(buffer_sf); if (ch != 2 || (bits != 16 && bits != 24 && bits != 32)) return; l = SOFT_VOL_SCALE; r = SOFT_VOL_SCALE; if (soft_vol && soft_vol_l != 100) l = soft_vol_db[soft_vol_l]; if (soft_vol && soft_vol_r != 100) r = soft_vol_db[soft_vol_r]; l *= replaygain_scale; r *= replaygain_scale; switch (bits) { case 16: SCALE_SAMPLES(int16_t, buffer, count, l, r, sf_need_swap(buffer_sf)); break; case 24: if (likely(!sf_get_bigendian(buffer_sf))) scale_samples_s24le(buffer, count, l, r); break; case 32: SCALE_SAMPLES(int32_t, buffer, count, l, r, sf_need_swap(buffer_sf)); break; } }
static int op_roar_open(sample_format_t sf, const channel_position_t *channel_map) { struct roar_audio_info info; int ret; memset(&info, 0, sizeof(info)); ROAR_DBG("op_roar_open(*) = ?"); format = sf; info.rate = sf_get_rate(sf); info.channels = sf_get_channels(sf); info.bits = sf_get_bits(sf); if (sf_get_bigendian(sf)) { if (sf_get_signed(sf)) { info.codec = ROAR_CODEC_PCM_S_BE; } else { info.codec = ROAR_CODEC_PCM_U_BE; } } else { if (sf_get_signed(sf)) { info.codec = ROAR_CODEC_PCM_S_LE; } else { info.codec = ROAR_CODEC_PCM_U_LE; } } ROAR_DBG("op_roar_open(*) = ?"); if (roar_libroar_set_server(host) == -1) { ROAR_DBG("op_roar_open(*) = ?"); roar_err_to_errno(); return -OP_ERROR_ERRNO; } if ( roar_simple_connect2(&con, NULL, "C* Music Player (cmus)", ROAR_ENUM_FLAG_NONBLOCK, 0) == -1 ) { ROAR_DBG("op_roar_open(*) = ?"); roar_err_to_errno(); return -OP_ERROR_ERRNO; } vss = roar_vs_new_from_con(&con, &err); if (vss == NULL) { ROAR_DBG("op_roar_open(*) = ?"); roar_disconnect(&con); _err_to_errno(); return -OP_ERROR_ERRNO; } if (roar_vs_stream(vss, &info, ROAR_DIR_PLAY, &err) == -1) { ROAR_DBG("op_roar_open(*) = ?"); roar_disconnect(&con); _err_to_errno(); return -OP_ERROR_ERRNO; } ROAR_DBG("op_roar_open(*) = ?"); if (roar_vs_buffer(vss, 2048*8, &err) == -1) { roar_vs_close(vss, ROAR_VS_TRUE, NULL); roar_disconnect(&con); _err_to_errno(); return -OP_ERROR_ERRNO; } ROAR_DBG("op_roar_open(*) = ?"); ret = _set_role(); if (ret != 0) { roar_vs_close(vss, ROAR_VS_TRUE, NULL); roar_disconnect(&con); _err_to_errno(); return ret; } ROAR_DBG("op_roar_open(*) = ?"); if (roar_vs_blocking(vss, ROAR_VS_FALSE, &err) == -1) { /* FIXME: handle this error */ } ROAR_DBG("op_roar_open(*) = 0"); return 0; }
static int oss_set_sf(sample_format_t sf) { int tmp, log2_fragment_size, nr_fragments, bytes_per_second; oss_reset(); oss_sf = sf; #ifdef SNDCTL_DSP_CHANNELS tmp = sf_get_channels(oss_sf); if (ioctl(oss_fd, SNDCTL_DSP_CHANNELS, &tmp) == -1) return -1; #else tmp = sf_get_channels(oss_sf) - 1; if (ioctl(oss_fd, SNDCTL_DSP_STEREO, &tmp) == -1) return -1; #endif if (sf_get_bits(oss_sf) == 16) { if (sf_get_signed(oss_sf)) { if (sf_get_bigendian(oss_sf)) { tmp = AFMT_S16_BE; } else { tmp = AFMT_S16_LE; } } else { if (sf_get_bigendian(oss_sf)) { tmp = AFMT_U16_BE; } else { tmp = AFMT_U16_LE; } } } else if (sf_get_bits(oss_sf) == 8) { if (sf_get_signed(oss_sf)) { tmp = AFMT_S8; } else { tmp = AFMT_U8; } } else if (sf_get_bits(oss_sf) == 32 && sf_get_signed(oss_sf)) { if (sf_get_bigendian(oss_sf)) { tmp = AFMT_S32_BE; } else { tmp = AFMT_S32_LE; } } else if (sf_get_bits(oss_sf) == 24 && sf_get_signed(oss_sf) && !sf_get_bigendian(oss_sf)) { tmp = AFMT_S24_PACKED; } else { d_print("unsupported sample format: %c%u_%s\n", sf_get_signed(oss_sf) ? 'S' : 'U', sf_get_bits(oss_sf), sf_get_bigendian(oss_sf) ? "BE" : "LE"); return -1; } if (ioctl(oss_fd, SNDCTL_DSP_SAMPLESIZE, &tmp) == -1) return -1; tmp = sf_get_rate(oss_sf); if (ioctl(oss_fd, SNDCTL_DSP_SPEED, &tmp) == -1) return -1; bytes_per_second = sf_get_second_size(oss_sf); log2_fragment_size = 0; while (1 << log2_fragment_size < bytes_per_second / 25) log2_fragment_size++; log2_fragment_size--; nr_fragments = 32; /* bits 0..15 = size of fragment, 16..31 = log2(number of fragments) */ tmp = (nr_fragments << 16) + log2_fragment_size; if (ioctl(oss_fd, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) return -1; return 0; }