static ALCboolean android_reset_playback(ALCdevice *device) { AndroidData* data = (AndroidData*)device->ExtraData; device->FmtChans = ChannelsFromDevFmt(device->FmtChans) >= 2 ? DevFmtStereo : DevFmtMono; SetDefaultChannelOrder(device); return ALC_TRUE; }
static ALCboolean android_reset_playback(ALCdevice *device) { g_device = device; AndroidData* data = (AndroidData*)device->ExtraData; device->FmtType = DevFmtShort; device->FmtChans = DevFmtStereo; SetDefaultChannelOrder(device); g_bufferLength = device->UpdateSize; g_bufferCount = device->NumUpdates; g_sampleRate = device->Frequency; g_mixerRunning = 1; return ALC_TRUE; }
static ALCboolean android_reset_playback(ALCdevice *device) { AndroidData* data = (AndroidData*)device->ExtraData; if (aluChannelsFromFormat(device->Format) >= 2) { device->Format = aluBytesFromFormat(device->Format) >= 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8; } else { device->Format = aluBytesFromFormat(device->Format) >= 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8; } SetDefaultChannelOrder(device); data->running = 1; pthread_create(&data->thread, NULL, thread_function, device); return ALC_TRUE; }
static ALCboolean pa_reset_playback(ALCdevice *device) { pa_data *data = (pa_data*)device->ExtraData; const PaStreamInfo *streamInfo; streamInfo = Pa_GetStreamInfo(data->stream); device->Frequency = streamInfo->sampleRate; device->UpdateSize = data->update_size; if(data->params.sampleFormat == paInt8) device->FmtType = DevFmtByte; else if(data->params.sampleFormat == paUInt8) device->FmtType = DevFmtUByte; else if(data->params.sampleFormat == paInt16) device->FmtType = DevFmtShort; else if(data->params.sampleFormat == paInt32) device->FmtType = DevFmtInt; else if(data->params.sampleFormat == paFloat32) device->FmtType = DevFmtFloat; else { ERR("Unexpected sample format: 0x%lx\n", data->params.sampleFormat); return ALC_FALSE; } if(data->params.channelCount == 2) device->FmtChans = DevFmtStereo; else if(data->params.channelCount == 1) device->FmtChans = DevFmtMono; else { ERR("Unexpected channel count: %u\n", data->params.channelCount); return ALC_FALSE; } SetDefaultChannelOrder(device); return ALC_TRUE; }
static ALCboolean oss_reset_playback(ALCdevice *device) { oss_data *data = (oss_data*)device->ExtraData; int numFragmentsLogSize; int log2FragmentSize; unsigned int periods; audio_buf_info info; ALuint frameSize; int numChannels; int ossFormat; int ossSpeed; char *err; switch(device->FmtType) { case DevFmtByte: ossFormat = AFMT_S8; break; case DevFmtUByte: ossFormat = AFMT_U8; break; case DevFmtUShort: case DevFmtInt: case DevFmtUInt: case DevFmtFloat: device->FmtType = DevFmtShort; /* fall-through */ case DevFmtShort: ossFormat = AFMT_S16_NE; break; } periods = device->NumUpdates; numChannels = ChannelsFromDevFmt(device->FmtChans); frameSize = numChannels * BytesFromDevFmt(device->FmtType); ossSpeed = device->Frequency; log2FragmentSize = log2i(device->UpdateSize * frameSize); /* according to the OSS spec, 16 bytes are the minimum */ if (log2FragmentSize < 4) log2FragmentSize = 4; /* Subtract one period since the temp mixing buffer counts as one. Still * need at least two on the card, though. */ if(periods > 2) periods--; numFragmentsLogSize = (periods << 16) | log2FragmentSize; #define CHECKERR(func) if((func) < 0) { \ err = #func; \ goto err; \ } /* Don't fail if SETFRAGMENT fails. We can handle just about anything * that's reported back via GETOSPACE */ ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize); CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat)); CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels)); CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed)); CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info)); if(0) { err: ERR("%s failed: %s\n", err, strerror(errno)); return ALC_FALSE; } #undef CHECKERR if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) { ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); return ALC_FALSE; } if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) || (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) || (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort))) { ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat); return ALC_FALSE; } device->Frequency = ossSpeed; device->UpdateSize = info.fragsize / frameSize; device->NumUpdates = info.fragments + 1; SetDefaultChannelOrder(device); return ALC_TRUE; }
static ALCboolean sndio_reset_playback(ALCdevice *device) { sndio_data *data = device->ExtraData; struct sio_par par; sio_initpar(&par); par.rate = device->Frequency; par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1); switch(device->FmtType) { case DevFmtByte: par.bits = 8; par.sig = 1; break; case DevFmtUByte: par.bits = 8; par.sig = 0; break; case DevFmtFloat: case DevFmtShort: par.bits = 16; par.sig = 1; break; case DevFmtUShort: par.bits = 16; par.sig = 0; break; case DevFmtInt: par.bits = 32; par.sig = 1; break; case DevFmtUInt: par.bits = 32; par.sig = 0; break; } par.le = SIO_LE_NATIVE; par.round = device->UpdateSize; par.appbufsz = device->UpdateSize * (device->NumUpdates-1); if(!par.appbufsz) par.appbufsz = device->UpdateSize; if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par)) { ERR("Failed to set device parameters\n"); return ALC_FALSE; } if(par.bits != par.bps*8) { ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8); return ALC_FALSE; } device->Frequency = par.rate; device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo); if(par.bits == 8 && par.sig == 1) device->FmtType = DevFmtByte; else if(par.bits == 8 && par.sig == 0) device->FmtType = DevFmtUByte; else if(par.bits == 16 && par.sig == 1) device->FmtType = DevFmtShort; else if(par.bits == 16 && par.sig == 0) device->FmtType = DevFmtUShort; else if(par.bits == 32 && par.sig == 1) device->FmtType = DevFmtInt; else if(par.bits == 32 && par.sig == 0) device->FmtType = DevFmtUInt; else { ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits); return ALC_FALSE; } device->UpdateSize = par.round; device->NumUpdates = (par.bufsz/par.round) + 1; SetDefaultChannelOrder(device); return ALC_TRUE; }
static ALCboolean qsa_reset_playback(ALCdevice* device) { qsa_data* data=(qsa_data*)device->ExtraData; int32_t format=-1; switch(device->FmtType) { case DevFmtByte: format=SND_PCM_SFMT_S8; break; case DevFmtUByte: format=SND_PCM_SFMT_U8; break; case DevFmtShort: format=SND_PCM_SFMT_S16_LE; break; case DevFmtUShort: format=SND_PCM_SFMT_U16_LE; break; case DevFmtInt: format=SND_PCM_SFMT_S32_LE; break; case DevFmtUInt: format=SND_PCM_SFMT_U32_LE; break; case DevFmtFloat: format=SND_PCM_SFMT_FLOAT_LE; break; } /* we actually don't want to block on writes */ snd_pcm_nonblock_mode(data->pcmHandle, 1); /* Disable mmap to control data transfer to the audio device */ snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP); snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS); // configure a sound channel memset(&data->cparams, 0, sizeof(data->cparams)); data->cparams.channel=SND_PCM_CHANNEL_PLAYBACK; data->cparams.mode=SND_PCM_MODE_BLOCK; data->cparams.start_mode=SND_PCM_START_FULL; data->cparams.stop_mode=SND_PCM_STOP_STOP; data->cparams.buf.block.frag_size=device->UpdateSize* ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType); data->cparams.buf.block.frags_max=device->NumUpdates; data->cparams.buf.block.frags_min=device->NumUpdates; data->cparams.format.interleave=1; data->cparams.format.rate=device->Frequency; data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans); data->cparams.format.format=format; if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0) { int original_rate=data->cparams.format.rate; int original_voices=data->cparams.format.voices; int original_format=data->cparams.format.format; int it; int jt; for (it=0; it<1; it++) { /* Check for second pass */ if (it==1) { original_rate=ratelist[0].rate; original_voices=channellist[0].channels; original_format=formatlist[0].format; } do { /* At first downgrade sample format */ jt=0; do { if (formatlist[jt].format==data->cparams.format.format) { data->cparams.format.format=formatlist[jt+1].format; break; } if (formatlist[jt].format==0) { data->cparams.format.format=0; break; } jt++; } while(1); if (data->cparams.format.format==0) { data->cparams.format.format=original_format; /* At secod downgrade sample rate */ jt=0; do { if (ratelist[jt].rate==data->cparams.format.rate) { data->cparams.format.rate=ratelist[jt+1].rate; break; } if (ratelist[jt].rate==0) { data->cparams.format.rate=0; break; } jt++; } while(1); if (data->cparams.format.rate==0) { data->cparams.format.rate=original_rate; data->cparams.format.format=original_format; /* At third downgrade channels number */ jt=0; do { if(channellist[jt].channels==data->cparams.format.voices) { data->cparams.format.voices=channellist[jt+1].channels; break; } if (channellist[jt].channels==0) { data->cparams.format.voices=0; break; } jt++; } while(1); } if (data->cparams.format.voices==0) { break; } } data->cparams.buf.block.frag_size=device->UpdateSize* data->cparams.format.voices* snd_pcm_format_width(data->cparams.format.format)/8; data->cparams.buf.block.frags_max=device->NumUpdates; data->cparams.buf.block.frags_min=device->NumUpdates; if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0) { continue; } else { break; } } while(1); if (data->cparams.format.voices!=0) { break; } } if (data->cparams.format.voices==0) { return ALC_FALSE; } } if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0) { return ALC_FALSE; } memset(&data->csetup, 0, sizeof(data->csetup)); data->csetup.channel=SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_setup(data->pcmHandle, &data->csetup)<0) { return ALC_FALSE; } /* now fill back to the our AL device */ device->Frequency=data->cparams.format.rate; switch (data->cparams.format.voices) { case 1: device->FmtChans=DevFmtMono; break; case 2: device->FmtChans=DevFmtStereo; break; case 4: device->FmtChans=DevFmtQuad; break; case 6: device->FmtChans=DevFmtX51; break; case 7: device->FmtChans=DevFmtX61; break; case 8: device->FmtChans=DevFmtX71; break; default: device->FmtChans=DevFmtMono; break; } switch (data->cparams.format.format) { case SND_PCM_SFMT_S8: device->FmtType=DevFmtByte; break; case SND_PCM_SFMT_U8: device->FmtType=DevFmtUByte; break; case SND_PCM_SFMT_S16_LE: device->FmtType=DevFmtShort; break; case SND_PCM_SFMT_U16_LE: device->FmtType=DevFmtUShort; break; case SND_PCM_SFMT_S32_LE: device->FmtType=DevFmtInt; break; case SND_PCM_SFMT_U32_LE: device->FmtType=DevFmtUInt; break; case SND_PCM_SFMT_FLOAT_LE: device->FmtType=DevFmtFloat; break; default: device->FmtType=DevFmtShort; break; } SetDefaultChannelOrder(device); device->UpdateSize=data->csetup.buf.block.frag_size/ (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType)); device->NumUpdates=data->csetup.buf.block.frags; data->size=data->csetup.buf.block.frag_size; data->buffer=malloc(data->size); if (!data->buffer) { return ALC_FALSE; } return ALC_TRUE; }
static ALCboolean alsa_reset_playback(ALCdevice *device) { alsa_data *data = (alsa_data*)device->ExtraData; snd_pcm_uframes_t periodSizeInFrames; unsigned int periodLen, bufferLen; snd_pcm_sw_params_t *sp = NULL; snd_pcm_hw_params_t *hp = NULL; snd_pcm_access_t access; snd_pcm_format_t format; unsigned int periods; unsigned int rate; const char *funcerr; int allowmmap; int err; format = -1; switch(device->FmtType) { case DevFmtByte: format = SND_PCM_FORMAT_S8; break; case DevFmtUByte: format = SND_PCM_FORMAT_U8; break; case DevFmtShort: format = SND_PCM_FORMAT_S16; break; case DevFmtUShort: format = SND_PCM_FORMAT_U16; break; case DevFmtInt: format = SND_PCM_FORMAT_S32; break; case DevFmtUInt: format = SND_PCM_FORMAT_U32; break; case DevFmtFloat: format = SND_PCM_FORMAT_FLOAT; break; } allowmmap = GetConfigValueBool("alsa", "mmap", 1); periods = device->NumUpdates; periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; bufferLen = periodLen * periods; rate = device->Frequency; snd_pcm_hw_params_malloc(&hp); #define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error CHECK(snd_pcm_hw_params_any(data->pcmHandle, hp)); /* set interleaved access */ if(!allowmmap || snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) { if(periods > 2) { periods--; bufferLen = periodLen * periods; } CHECK(snd_pcm_hw_params_set_access(data->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED)); } /* test and set format (implicitly sets sample bits) */ if(snd_pcm_hw_params_test_format(data->pcmHandle, hp, format) < 0) { static const struct { snd_pcm_format_t format; enum DevFmtType fmttype; } formatlist[] = { { SND_PCM_FORMAT_FLOAT, DevFmtFloat }, { SND_PCM_FORMAT_S32, DevFmtInt }, { SND_PCM_FORMAT_U32, DevFmtUInt }, { SND_PCM_FORMAT_S16, DevFmtShort }, { SND_PCM_FORMAT_U16, DevFmtUShort }, { SND_PCM_FORMAT_S8, DevFmtByte }, { SND_PCM_FORMAT_U8, DevFmtUByte }, }; size_t k; for(k = 0;k < COUNTOF(formatlist);k++) { format = formatlist[k].format; if(snd_pcm_hw_params_test_format(data->pcmHandle, hp, format) >= 0) { device->FmtType = formatlist[k].fmttype; break; } } } CHECK(snd_pcm_hw_params_set_format(data->pcmHandle, hp, format)); /* test and set channels (implicitly sets frame bits) */ if(snd_pcm_hw_params_test_channels(data->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)) < 0) { static const enum DevFmtChannels channellist[] = { DevFmtStereo, DevFmtQuad, DevFmtX51, DevFmtX71, DevFmtMono, }; size_t k; for(k = 0;k < COUNTOF(channellist);k++) { if(snd_pcm_hw_params_test_channels(data->pcmHandle, hp, ChannelsFromDevFmt(channellist[k])) >= 0) { device->FmtChans = channellist[k]; break; } } } CHECK(snd_pcm_hw_params_set_channels(data->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); /* set rate (implicitly constrains period/buffer parameters) */ if(snd_pcm_hw_params_set_rate_resample(data->pcmHandle, hp, 0) < 0) ERR("Failed to disable ALSA resampler\n"); CHECK(snd_pcm_hw_params_set_rate_near(data->pcmHandle, hp, &rate, NULL)); /* set buffer time (implicitly constrains period/buffer parameters) */ CHECK(snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, hp, &bufferLen, NULL)); /* set period time (implicitly sets buffer size/bytes/time and period size/bytes) */ CHECK(snd_pcm_hw_params_set_period_time_near(data->pcmHandle, hp, &periodLen, NULL)); /* install and prepare hardware configuration */ CHECK(snd_pcm_hw_params(data->pcmHandle, hp)); /* retrieve configuration info */ CHECK(snd_pcm_hw_params_get_access(hp, &access)); CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL)); CHECK(snd_pcm_hw_params_get_periods(hp, &periods, NULL)); snd_pcm_hw_params_free(hp); hp = NULL; snd_pcm_sw_params_malloc(&sp); CHECK(snd_pcm_sw_params_current(data->pcmHandle, sp)); CHECK(snd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)); CHECK(snd_pcm_sw_params_set_stop_threshold(data->pcmHandle, sp, periodSizeInFrames*periods)); CHECK(snd_pcm_sw_params(data->pcmHandle, sp)); #undef CHECK snd_pcm_sw_params_free(sp); sp = NULL; /* Increase periods by one, since the temp buffer counts as an extra * period */ if(access == SND_PCM_ACCESS_RW_INTERLEAVED) device->NumUpdates = periods+1; else device->NumUpdates = periods; device->UpdateSize = periodSizeInFrames; device->Frequency = rate; SetDefaultChannelOrder(device); return ALC_TRUE; error: ERR("%s failed: %s\n", funcerr, snd_strerror(err)); if(hp) snd_pcm_hw_params_free(hp); if(sp) snd_pcm_sw_params_free(sp); return ALC_FALSE; }
static ALCboolean alsa_reset_playback(ALCdevice *device) { alsa_data *data = (alsa_data*)device->ExtraData; snd_pcm_uframes_t periodSizeInFrames; unsigned int periodLen, bufferLen; snd_pcm_sw_params_t *sp = NULL; snd_pcm_hw_params_t *p = NULL; snd_pcm_access_t access; snd_pcm_format_t format; unsigned int periods; unsigned int rate; int allowmmap; char *err; int i; switch(aluBytesFromFormat(device->Format)) { case 1: format = SND_PCM_FORMAT_U8; break; case 2: format = SND_PCM_FORMAT_S16; break; case 4: format = SND_PCM_FORMAT_FLOAT; break; default: AL_PRINT("Unknown format: 0x%x\n", device->Format); return ALC_FALSE; } allowmmap = GetConfigValueBool("alsa", "mmap", 1); periods = device->NumUpdates; periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; rate = device->Frequency; err = NULL; psnd_pcm_hw_params_malloc(&p); if((i=psnd_pcm_hw_params_any(data->pcmHandle, p)) < 0) err = "any"; /* set interleaved access */ if(i >= 0 && (!allowmmap || (i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)) { if(periods > 2) periods--; if((i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) err = "set access"; } /* set format (implicitly sets sample bits) */ if(i >= 0 && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0) { switch(aluChannelsFromFormat(device->Format)) { case 1: device->Format = AL_FORMAT_MONO_FLOAT32; break; case 2: device->Format = AL_FORMAT_STEREO_FLOAT32; break; case 4: device->Format = AL_FORMAT_QUAD32; break; case 6: device->Format = AL_FORMAT_51CHN32; break; case 7: device->Format = AL_FORMAT_61CHN32; break; case 8: device->Format = AL_FORMAT_71CHN32; break; } if((i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_FLOAT)) < 0) { switch(aluChannelsFromFormat(device->Format)) { case 1: device->Format = AL_FORMAT_MONO16; break; case 2: device->Format = AL_FORMAT_STEREO16; break; case 4: device->Format = AL_FORMAT_QUAD16; break; case 6: device->Format = AL_FORMAT_51CHN16; break; case 7: device->Format = AL_FORMAT_61CHN16; break; case 8: device->Format = AL_FORMAT_71CHN16; break; } if((i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_S16)) < 0) { switch(aluChannelsFromFormat(device->Format)) { case 1: device->Format = AL_FORMAT_MONO8; break; case 2: device->Format = AL_FORMAT_STEREO8; break; case 4: device->Format = AL_FORMAT_QUAD8; break; case 6: device->Format = AL_FORMAT_51CHN8; break; case 7: device->Format = AL_FORMAT_61CHN8; break; case 8: device->Format = AL_FORMAT_71CHN8; break; } if((i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_U8)) < 0) err = "set format"; } } } /* set channels (implicitly sets frame bits) */ if(i >= 0 && (i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(device->Format))) < 0) { switch(aluBytesFromFormat(device->Format)) { case 1: device->Format = AL_FORMAT_STEREO8; break; case 2: device->Format = AL_FORMAT_STEREO16; break; case 4: device->Format = AL_FORMAT_STEREO_FLOAT32; break; } if((i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, 2)) < 0) { switch(aluBytesFromFormat(device->Format)) { case 1: device->Format = AL_FORMAT_MONO8; break; case 2: device->Format = AL_FORMAT_MONO16; break; case 4: device->Format = AL_FORMAT_MONO_FLOAT32; break; } if((i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, 1)) < 0) err = "set channels"; } } if(i >= 0 && (i=psnd_pcm_hw_params_set_rate_resample(data->pcmHandle, p, 0)) < 0) { AL_PRINT("Failed to disable ALSA resampler\n"); i = 0; } /* set rate (implicitly constrains period/buffer parameters) */ if(i >= 0 && (i=psnd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &rate, NULL)) < 0) err = "set rate near"; /* set buffer time (implicitly constrains period/buffer parameters) */ bufferLen = periodLen * periods; if(i >= 0 && (i=psnd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, p, &bufferLen, NULL)) < 0) err = "set buffer time near"; /* set period time in frame units (implicitly sets buffer size/bytes/time and period size/bytes) */ if(i >= 0 && (i=psnd_pcm_hw_params_set_period_time_near(data->pcmHandle, p, &periodLen, NULL)) < 0) err = "set period time near"; /* install and prepare hardware configuration */ if(i >= 0 && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0) err = "set params"; if(i >= 0 && (i=psnd_pcm_hw_params_get_access(p, &access)) < 0) err = "get access"; if(i >= 0 && (i=psnd_pcm_hw_params_get_period_size(p, &periodSizeInFrames, NULL)) < 0) err = "get period size"; if(i >= 0 && (i=psnd_pcm_hw_params_get_periods(p, &periods, NULL)) < 0) err = "get periods"; if(i < 0) { AL_PRINT("%s failed: %s\n", err, psnd_strerror(i)); psnd_pcm_hw_params_free(p); return ALC_FALSE; } psnd_pcm_hw_params_free(p); err = NULL; psnd_pcm_sw_params_malloc(&sp); if((i=psnd_pcm_sw_params_current(data->pcmHandle, sp)) != 0) err = "sw current"; if(i == 0 && (i=psnd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)) != 0) err = "sw set avail min"; if(i == 0 && (i=psnd_pcm_sw_params(data->pcmHandle, sp)) != 0) err = "sw set params"; if(i != 0) { AL_PRINT("%s failed: %s\n", err, psnd_strerror(i)); psnd_pcm_sw_params_free(sp); return ALC_FALSE; } psnd_pcm_sw_params_free(sp); SetDefaultChannelOrder(device); data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames); if(access == SND_PCM_ACCESS_RW_INTERLEAVED) { /* Increase periods by one, since the temp buffer counts as an extra * period */ periods++; data->buffer = malloc(data->size); if(!data->buffer) { AL_PRINT("buffer malloc failed\n"); return ALC_FALSE; } device->UpdateSize = periodSizeInFrames; device->NumUpdates = periods; device->Frequency = rate; data->thread = StartThread(ALSANoMMapProc, device); } else { i = psnd_pcm_prepare(data->pcmHandle); if(i < 0) { AL_PRINT("prepare error: %s\n", psnd_strerror(i)); return ALC_FALSE; } device->UpdateSize = periodSizeInFrames; device->NumUpdates = periods; device->Frequency = rate; data->thread = StartThread(ALSAProc, device); } if(data->thread == NULL) { AL_PRINT("Could not create playback thread\n"); free(data->buffer); data->buffer = NULL; return ALC_FALSE; } return ALC_TRUE; }
static ALCboolean oss_reset_playback( ALCdevice* device ) { oss_data* data = ( oss_data* )device->ExtraData; int numFragmentsLogSize; int log2FragmentSize; unsigned int periods; audio_buf_info info; ALuint frameSize; int numChannels; int ossFormat; int ossSpeed; char* err; int i; switch ( aluBytesFromFormat( device->Format ) ) { case 1: ossFormat = AFMT_U8; break; case 4: switch ( aluChannelsFromFormat( device->Format ) ) { case 1: device->Format = AL_FORMAT_MONO16; break; case 2: device->Format = AL_FORMAT_STEREO16; break; case 4: device->Format = AL_FORMAT_QUAD16; break; case 6: device->Format = AL_FORMAT_51CHN16; break; case 7: device->Format = AL_FORMAT_61CHN16; break; case 8: device->Format = AL_FORMAT_71CHN16; break; } /* fall-through */ case 2: ossFormat = AFMT_S16_NE; break; default: AL_PRINT( "Unknown format: 0x%x\n", device->Format ); return ALC_FALSE; } periods = device->NumUpdates; numChannels = aluChannelsFromFormat( device->Format ); frameSize = numChannels * aluBytesFromFormat( device->Format ); ossSpeed = device->Frequency; log2FragmentSize = log2i( device->UpdateSize * frameSize ); /* according to the OSS spec, 16 bytes are the minimum */ if ( log2FragmentSize < 4 ) { log2FragmentSize = 4; } /* Subtract one period since the temp mixing buffer counts as one. Still * need at least two on the card, though. */ if ( periods > 2 ) { periods--; } numFragmentsLogSize = ( periods << 16 ) | log2FragmentSize; #define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1)) /* Don't fail if SETFRAGMENT fails. We can handle just about anything * that's reported back via GETOSPACE */ ioctl( data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize ); if ( !( ok( ioctl( data->fd, SNDCTL_DSP_SETFMT, &ossFormat ), "set format" ) && ok( ioctl( data->fd, SNDCTL_DSP_CHANNELS, &numChannels ), "set channels" ) && ok( ioctl( data->fd, SNDCTL_DSP_SPEED, &ossSpeed ), "set speed" ) && ok( ioctl( data->fd, SNDCTL_DSP_GETOSPACE, &info ), "get space" ) ) ) { AL_PRINT( "%s failed: %s\n", err, strerror( errno ) ); return ALC_FALSE; } #undef ok if ( ( int )aluChannelsFromFormat( device->Format ) != numChannels ) { AL_PRINT( "Could not set %d channels, got %d instead\n", aluChannelsFromFormat( device->Format ), numChannels ); return ALC_FALSE; } if ( !( ( ossFormat == AFMT_U8 && aluBytesFromFormat( device->Format ) == 1 ) || ( ossFormat == AFMT_S16_NE && aluBytesFromFormat( device->Format ) == 2 ) ) ) { AL_PRINT( "Could not set %d-bit output, got format %#x\n", aluBytesFromFormat( device->Format ) * 8, ossFormat ); return ALC_FALSE; } device->Frequency = ossSpeed; device->UpdateSize = info.fragsize / frameSize; device->NumUpdates = info.fragments + 1; data->data_size = device->UpdateSize * frameSize; data->mix_data = calloc( 1, data->data_size ); SetDefaultChannelOrder( device ); data->thread = StartThread( OSSProc, device ); if ( data->thread == NULL ) { free( data->mix_data ); data->mix_data = NULL; return ALC_FALSE; } return ALC_TRUE; }
static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName) { const PaStreamInfo *streamInfo; PaStreamParameters outParams; pa_data *data; PaError err; if(!deviceName) deviceName = pa_device; else if(strcmp(deviceName, pa_device) != 0) return ALC_FALSE; if(!pa_load()) return ALC_FALSE; data = (pa_data*)calloc(1, sizeof(pa_data)); data->update_size = device->UpdateSize; device->ExtraData = data; outParams.device = GetConfigValueInt("port", "device", -1); if(outParams.device < 0) outParams.device = pPa_GetDefaultOutputDevice(); outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) / (float)device->Frequency; outParams.hostApiSpecificStreamInfo = NULL; switch(aluBytesFromFormat(device->Format)) { case 1: outParams.sampleFormat = paUInt8; break; case 2: outParams.sampleFormat = paInt16; break; case 4: outParams.sampleFormat = paFloat32; break; default: AL_PRINT("Unknown format: 0x%x\n", device->Format); device->ExtraData = NULL; free(data); return ALC_FALSE; } outParams.channelCount = aluChannelsFromFormat(device->Format); SetDefaultChannelOrder(device); err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency, device->UpdateSize, paNoFlag, pa_callback, device); if(err != paNoError) { AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err)); device->ExtraData = NULL; free(data); return ALC_FALSE; } streamInfo = pPa_GetStreamInfo(data->stream); device->szDeviceName = strdup(deviceName); device->Frequency = streamInfo->sampleRate; return ALC_TRUE; }
static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; audio_info_t info; ALsizei frameSize; ALsizei numChannels; AUDIO_INITINFO(&info); info.play.sample_rate = device->Frequency; if(device->FmtChans != DevFmtMono) device->FmtChans = DevFmtStereo; numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); info.play.channels = numChannels; switch(device->FmtType) { case DevFmtByte: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_LINEAR; break; case DevFmtUByte: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_LINEAR8; break; case DevFmtUShort: case DevFmtInt: case DevFmtUInt: case DevFmtFloat: device->FmtType = DevFmtShort; /* fall-through */ case DevFmtShort: info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; break; } frameSize = numChannels * BytesFromDevFmt(device->FmtType); info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; if(ioctl(self->fd, AUDIO_SETINFO, &info) < 0) { ERR("ioctl failed: %s\n", strerror(errno)); return ALC_FALSE; } if(ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)info.play.channels) { ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), info.play.channels); return ALC_FALSE; } if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) || (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) || (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) || (info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt))) { ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType), info.play.precision, info.play.encoding); return ALC_FALSE; } device->Frequency = info.play.sample_rate; device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; SetDefaultChannelOrder(device); free(self->mix_data); self->data_size = device->UpdateSize * FrameSizeFromDevFmt( device->FmtChans, device->FmtType, device->AmbiOrder ); self->mix_data = calloc(1, self->data_size); return ALC_TRUE; }
static ALCboolean solaris_reset_playback(ALCdevice *device) { solaris_data *data = (solaris_data*)device->ExtraData; audio_info_t info; ALuint frameSize; int numChannels; AUDIO_INITINFO(&info); info.play.sample_rate = device->Frequency; if(device->FmtChans != DevFmtMono) device->FmtChans = DevFmtStereo; numChannels = ChannelsFromDevFmt(device->FmtChans); info.play.channels = numChannels; switch(device->FmtType) { case DevFmtByte: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_LINEAR; break; case DevFmtUByte: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_LINEAR8; break; case DevFmtUShort: case DevFmtInt: case DevFmtUInt: case DevFmtFloat: device->FmtType = DevFmtShort; /* fall-through */ case DevFmtShort: info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; break; } frameSize = numChannels * BytesFromDevFmt(device->FmtType); info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0) { ERR("ioctl failed: %s\n", strerror(errno)); return ALC_FALSE; } if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels) { ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels); return ALC_FALSE; } if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) || (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) || (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) || (info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt))) { ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType), info.play.precision, info.play.encoding); return ALC_FALSE; } device->Frequency = info.play.sample_rate; device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; SetDefaultChannelOrder(device); return ALC_TRUE; }
static ALCboolean solaris_reset_playback(ALCdevice *device) { solaris_data *data = (solaris_data*)device->ExtraData; audio_info_t info; ALuint frameSize; int numChannels; AUDIO_INITINFO(&info); switch(aluBytesFromFormat(device->Format)) { case 1: info.play.precision = 8; info.play.encoding = AUDIO_ENCODING_LINEAR8; break; case 4: switch(numChannels) { case 1: device->Format = AL_FORMAT_MONO16; break; case 2: device->Format = AL_FORMAT_STEREO16; break; case 4: device->Format = AL_FORMAT_QUAD16; break; case 6: device->Format = AL_FORMAT_51CHN16; break; case 7: device->Format = AL_FORMAT_61CHN16; break; case 8: device->Format = AL_FORMAT_71CHN16; break; } /* fall-through */ case 2: info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; break; default: AL_PRINT("Unknown format: 0x%x\n", device->Format); return ALC_FALSE; } numChannels = aluChannelsFromFormat(device->Format); info.play.sample_rate = device->Frequency; info.play.channels = numChannels; frameSize = numChannels * aluBytesFromFormat(device->Format); info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0) { AL_PRINT("ioctl failed: %s\n", strerror(errno)); return ALC_FALSE; } if(aluChannelsFromFormat(device->Format) != info.play.channels) { AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), info.play.channels); return ALC_FALSE; } if(!((info.play.precision == 8 && aluBytesFromFormat(device->Format) == 1) || (info.play.precision == 16 && aluBytesFromFormat(device->Format) == 2))) { AL_PRINT("Could not set %d-bit output, got %d\n", aluBytesFromFormat(device->Format)*8, info.play.precision); return ALC_FALSE; } device->Frequency = info.play.sample_rate; device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; data->data_size = device->UpdateSize * frameSize; data->mix_data = calloc(1, data->data_size); SetDefaultChannelOrder(device); data->thread = StartThread(SolarisProc, device); if(data->thread == NULL) { free(data->mix_data); data->mix_data = NULL; return ALC_FALSE; } return ALC_TRUE; }
static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName) { PaStreamParameters outParams; pa_data *data; PaError err; if(!deviceName) deviceName = pa_device; else if(strcmp(deviceName, pa_device) != 0) return ALC_INVALID_VALUE; data = (pa_data*)calloc(1, sizeof(pa_data)); data->update_size = device->UpdateSize; device->ExtraData = data; outParams.device = -1; if(!ConfigValueInt("port", "device", &outParams.device) || outParams.device < 0) outParams.device = Pa_GetDefaultOutputDevice(); outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) / (float)device->Frequency; outParams.hostApiSpecificStreamInfo = NULL; switch(device->FmtType) { case DevFmtByte: outParams.sampleFormat = paInt8; break; case DevFmtUByte: outParams.sampleFormat = paUInt8; break; case DevFmtUShort: device->FmtType = DevFmtShort; /* fall-through */ case DevFmtShort: outParams.sampleFormat = paInt16; break; case DevFmtFloat: outParams.sampleFormat = paFloat32; break; } outParams.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2); SetDefaultChannelOrder(device); err = Pa_OpenStream(&data->stream, NULL, &outParams, device->Frequency, device->UpdateSize, paNoFlag, pa_callback, device); if(err != paNoError) { ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err)); device->ExtraData = NULL; free(data); return ALC_INVALID_VALUE; } device->szDeviceName = strdup(deviceName); if((ALuint)outParams.channelCount != ChannelsFromDevFmt(device->FmtChans)) { if(outParams.channelCount != 1 && outParams.channelCount != 2) { ERR("Unhandled channel count: %u\n", outParams.channelCount); Pa_CloseStream(data->stream); device->ExtraData = NULL; free(data); return ALC_INVALID_VALUE; } if((device->Flags&DEVICE_CHANNELS_REQUEST)) ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), outParams.channelCount); device->Flags &= ~DEVICE_CHANNELS_REQUEST; device->FmtChans = ((outParams.channelCount==1) ? DevFmtMono : DevFmtStereo); } return ALC_NO_ERROR; }
static ALCboolean alsa_reset_playback(ALCdevice *device) { alsa_data *data = (alsa_data*)device->ExtraData; snd_pcm_uframes_t periodSizeInFrames; unsigned int periodLen, bufferLen; snd_pcm_sw_params_t *sp = NULL; snd_pcm_hw_params_t *p = NULL; snd_pcm_access_t access; snd_pcm_format_t format; unsigned int periods; unsigned int rate; int allowmmap; char *err; int i; format = -1; switch(device->FmtType) { case DevFmtByte: format = SND_PCM_FORMAT_S8; break; case DevFmtUByte: format = SND_PCM_FORMAT_U8; break; case DevFmtShort: format = SND_PCM_FORMAT_S16; break; case DevFmtUShort: format = SND_PCM_FORMAT_U16; break; case DevFmtFloat: format = SND_PCM_FORMAT_FLOAT; break; } allowmmap = GetConfigValueBool("alsa", "mmap", 1); periods = device->NumUpdates; periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; bufferLen = periodLen * periods; rate = device->Frequency; err = NULL; snd_pcm_hw_params_malloc(&p); if((i=snd_pcm_hw_params_any(data->pcmHandle, p)) < 0) err = "any"; /* set interleaved access */ if(i >= 0 && (!allowmmap || (i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)) { if(periods > 2) { periods--; bufferLen = periodLen * periods; } if((i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) err = "set access"; } /* set format (implicitly sets sample bits) */ if(i >= 0 && (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0) { device->FmtType = DevFmtFloat; if(format == SND_PCM_FORMAT_FLOAT || (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_FLOAT)) < 0) { device->FmtType = DevFmtShort; if(format == SND_PCM_FORMAT_S16 || (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_S16)) < 0) { device->FmtType = DevFmtUByte; if(format == SND_PCM_FORMAT_U8 || (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_U8)) < 0) err = "set format"; } } } /* set channels (implicitly sets frame bits) */ if(i >= 0 && (i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, ChannelsFromDevFmt(device->FmtChans))) < 0) { if((i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, 2)) < 0) { if((i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, 1)) < 0) err = "set channels"; else device->FmtChans = DevFmtMono; } else device->FmtChans = DevFmtStereo; } if(i >= 0 && (i=snd_pcm_hw_params_set_rate_resample(data->pcmHandle, p, 0)) < 0) { ERR("Failed to disable ALSA resampler\n"); i = 0; } /* set rate (implicitly constrains period/buffer parameters) */ if(i >= 0 && (i=snd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &rate, NULL)) < 0) err = "set rate near"; /* set buffer time (implicitly constrains period/buffer parameters) */ if(i >= 0 && (i=snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, p, &bufferLen, NULL)) < 0) err = "set buffer time near"; /* set period time in frame units (implicitly sets buffer size/bytes/time and period size/bytes) */ if(i >= 0 && (i=snd_pcm_hw_params_set_period_time_near(data->pcmHandle, p, &periodLen, NULL)) < 0) err = "set period time near"; /* install and prepare hardware configuration */ if(i >= 0 && (i=snd_pcm_hw_params(data->pcmHandle, p)) < 0) err = "set params"; if(i >= 0 && (i=snd_pcm_hw_params_get_access(p, &access)) < 0) err = "get access"; if(i >= 0 && (i=snd_pcm_hw_params_get_period_size(p, &periodSizeInFrames, NULL)) < 0) err = "get period size"; if(i >= 0 && (i=snd_pcm_hw_params_get_periods(p, &periods, NULL)) < 0) err = "get periods"; if(i < 0) { ERR("%s failed: %s\n", err, snd_strerror(i)); snd_pcm_hw_params_free(p); return ALC_FALSE; } snd_pcm_hw_params_free(p); err = NULL; snd_pcm_sw_params_malloc(&sp); if((i=snd_pcm_sw_params_current(data->pcmHandle, sp)) != 0) err = "sw current"; if(i == 0 && (i=snd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)) != 0) err = "sw set avail min"; if(i == 0 && (i=snd_pcm_sw_params_set_stop_threshold(data->pcmHandle, sp, periodSizeInFrames*periods)) != 0) err = "sw set stop threshold"; if(i == 0 && (i=snd_pcm_sw_params(data->pcmHandle, sp)) != 0) err = "sw set params"; if(i != 0) { ERR("%s failed: %s\n", err, snd_strerror(i)); snd_pcm_sw_params_free(sp); return ALC_FALSE; } snd_pcm_sw_params_free(sp); device->Frequency = rate; SetDefaultChannelOrder(device); data->size = snd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames); if(access == SND_PCM_ACCESS_RW_INTERLEAVED) { /* Increase periods by one, since the temp buffer counts as an extra * period */ periods++; data->buffer = malloc(data->size); if(!data->buffer) { ERR("buffer malloc failed\n"); return ALC_FALSE; } device->UpdateSize = periodSizeInFrames; device->NumUpdates = periods; data->thread = StartThread(ALSANoMMapProc, device); } else { i = snd_pcm_prepare(data->pcmHandle); if(i < 0) { ERR("prepare error: %s\n", snd_strerror(i)); return ALC_FALSE; } device->UpdateSize = periodSizeInFrames; device->NumUpdates = periods; data->thread = StartThread(ALSAProc, device); } if(data->thread == NULL) { ERR("Could not create playback thread\n"); free(data->buffer); data->buffer = NULL; return ALC_FALSE; } return ALC_TRUE; }