snd_pcm_t *open_pcm(char *pcm_name) { snd_pcm_t *playback_handle; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; if (snd_pcm_open (&playback_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) { fprintf (stderr, "cannot open audio device %s\n", pcm_name); exit (1); } snd_pcm_hw_params_alloca(&hw_params); snd_pcm_hw_params_any(playback_handle, hw_params); snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, 44100, 0); snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2); snd_pcm_hw_params_set_periods(playback_handle, hw_params, 2, 0); snd_pcm_hw_params_set_period_size(playback_handle, hw_params, BUFSIZE, 0); snd_pcm_hw_params(playback_handle, hw_params); snd_pcm_sw_params_alloca(&sw_params); snd_pcm_sw_params_current(playback_handle, sw_params); snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, BUFSIZE); snd_pcm_sw_params(playback_handle, sw_params); return(playback_handle); }
static void alsa_set_hw_params(struct alsa_dev *dev, snd_pcm_t *handle, unsigned int rate, int channels, int period) { int dir, ret; snd_pcm_uframes_t period_size; snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_t *hw_params; ret = snd_pcm_hw_params_malloc(&hw_params); if (ret < 0) syslog_panic("Cannot allocate hardware parameters: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_any(handle, hw_params); if (ret < 0) syslog_panic("Cannot initialize hardware parameters: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (ret < 0) syslog_panic("Cannot set access type: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE); if (ret < 0) syslog_panic("Cannot set sample format: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_rate_near(handle, hw_params, &rate, 0); if (ret < 0) syslog_panic("Cannot set sample rate: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_channels(handle, hw_params, channels); if (ret < 0) syslog_panic("Cannot set channel number: %s\n", snd_strerror(ret)); period_size = period; dir = 0; ret = snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, &dir); if (ret < 0) syslog_panic("Cannot set period size: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params_set_periods(handle, hw_params, PERIODS, 0); if (ret < 0) syslog_panic("Cannot set period number: %s\n", snd_strerror(ret)); buffer_size = period_size * PERIODS; dir = 0; ret = snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size); if (ret < 0) syslog_panic("Cannot set buffer size: %s\n", snd_strerror(ret)); ret = snd_pcm_hw_params(handle, hw_params); if (ret < 0) syslog_panic("Cannot set capture parameters: %s\n", snd_strerror(ret)); snd_pcm_hw_params_free(hw_params); }
static int setup_playback(void) { int err; snd_pcm_hw_params_t *pcm_params; if ((err = snd_pcm_hw_params_malloc(&pcm_params)) < 0 || (err = snd_pcm_hw_params_any(pcm_handle, pcm_params)) < 0 || (err = snd_pcm_hw_params_set_access(pcm_handle, pcm_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0 || (err = snd_pcm_hw_params_set_format(pcm_handle, pcm_params, pcm_format)) < 0 || (err = snd_pcm_hw_params_set_rate_near(pcm_handle, pcm_params, &pcm_hz, 0)) < 0 || (err = snd_pcm_hw_params_set_channels(pcm_handle, pcm_params, 1)) < 0) { module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("params setup error: %s\n"), snd_strerror(err)); return 0; } #if 0 // ??? pcm_samplesize = pcm_periodsize * pcm_periods / pcm_framesize; if ((err = snd_pcm_hw_params_set_periods(pcm_handle, pcm_params, pcm_periods, 0)) < 0 || (err = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, pcm_params, &pcm_samplesize)) < 0) { module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("cannot set up period size: %s\n"), snd_strerror(err)); // continue } samplebuf = (s8 *) malloc(pcm_samplesize * pcm_framesize); #else pcm_samplesize = pcm_periodsize; samplebuf = (s16 *) malloc(pcm_samplesize * sizeof(samplebuf[0])); #endif if ((err = snd_pcm_hw_params(pcm_handle, pcm_params)) < 0) { module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("params setting error: %s\n"), snd_strerror(err)); return 0; } snd_pcm_hw_params_free(pcm_params); if ((err = snd_pcm_prepare(pcm_handle)) < 0) { module_logger(&alsaSound, _L|LOG_USER | LOG_ERROR, _("error preparing PCM handle\n"), snd_strerror(err)); return 0; } return 1; }
int audio_drv_init(void) { unsigned int rate = 44100; int err; snd_pcm_hw_params_t *hw_params; if ((err = snd_pcm_open(&playback_handle, "hw", SND_PCM_STREAM_PLAYBACK, 0)) < 0) return -1; if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) return -2; if ((err = snd_pcm_hw_params_any(playback_handle, hw_params)) < 0) return -3; if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) return -4; if ((err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) return -5; if ((err = snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0)) < 0) return -6; if ((err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2)) < 0) return -7; if ((err = snd_pcm_hw_params_set_period_size(playback_handle, hw_params, 4096, 0)) < 0) return -8; if ((err = snd_pcm_hw_params_set_periods(playback_handle, hw_params, 4, 0)) < 0) return -9; if ((err = snd_pcm_hw_params(playback_handle, hw_params)) < 0) return -10; snd_pcm_hw_params_free(hw_params); if ((err = snd_pcm_prepare(playback_handle)) < 0) return -11; return 0; }
snd_pcm_t *open_pcm(char *pcm_name) { snd_pcm_t *playback_handle; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; if (snd_pcm_open (&playback_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) { fprintf (stderr, "cannot open audio device %s\n", pcm_name); return NULL;//it seems greedy and wants exclusive control?! } snd_pcm_hw_params_alloca(&hw_params); snd_pcm_hw_params_any(playback_handle, hw_params); snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0); snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2); snd_pcm_hw_params_set_periods(playback_handle, hw_params, 2, 0); snd_pcm_hw_params_set_period_size(playback_handle, hw_params, BUFSAMPS, 0); snd_pcm_hw_params(playback_handle, hw_params); snd_pcm_sw_params_alloca(&sw_params); snd_pcm_sw_params_current(playback_handle, sw_params); snd_pcm_sw_params_set_avail_min(playback_handle, sw_params, BUFSAMPS); snd_pcm_sw_params(playback_handle, sw_params); return(playback_handle); }
/* ------- PCM INITS --------------------------------- */ static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params,int *chs) { #ifndef ALSAAPI9 unsigned int rrate; int err, dir; int channels_allocated = 0; /* choose all parameters */ err = snd_pcm_hw_params_any(handle, params); if (err < 0) { check_error(err,"Broken configuration: no configurations available"); return err; } /* set the nointerleaved read/write format */ err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); if (err >= 0) { #ifdef ALSAMM_DEBUG if(sys_verbose) post("Access type %s available","SND_PCM_ACCESS_MMAP_NONINTERLEAVED"); #endif } else{ check_error(err,"No Accesstype SND_PCM_ACCESS_MMAP_NONINTERLEAVED"); return err; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, params, ALSAMM_FORMAT); if (err < 0) { check_error(err,"Sample format not available for playback"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Setting format to %s",snd_pcm_format_name(ALSAMM_FORMAT)); #endif /* first check samplerate since channels numbers are samplerate dependent (double speed) */ /* set the stream rate */ rrate = alsamm_sr; #ifdef ALSAMM_DEBUG if(sys_verbose) post("Samplerate request: %i Hz",rrate); #endif dir=-1; err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, &dir); if (err < 0) { check_error(err,"Rate not available"); return err; } if (rrate != alsamm_sr) { post("Warning: rate %iHz doesn't match requested %iHz", rrate,alsamm_sr); alsamm_sr = rrate; } else if(sys_verbose) post("Samplerate is set to %iHz",alsamm_sr); /* Info on channels */ { int maxchs,minchs,channels = *chs; if((err = snd_pcm_hw_params_get_channels_max(params, (unsigned int *)&maxchs)) < 0){ check_error(err,"Getting channels_max not available"); return err; } if((err = snd_pcm_hw_params_get_channels_min(params, (unsigned int *)&minchs)) < 0){ check_error(err,"Getting channels_min not available"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Getting channels:min=%d, max= %d for request=%d",minchs,maxchs,channels); #endif if(channels < 0)channels=maxchs; if(channels > maxchs)channels = maxchs; if(channels < minchs)channels = minchs; if(channels != *chs) post("requested channels=%d but used=%d",*chs,channels); *chs = channels; #ifdef ALSAMM_DEBUG if(sys_verbose) post("trying to use channels: %d",channels); #endif } /* set the count of channels */ err = snd_pcm_hw_params_set_channels(handle, params, *chs); if (err < 0) { check_error(err,"Channels count not available"); return err; } /* testing for channels */ if((err = snd_pcm_hw_params_get_channels(params,(unsigned int *)chs)) < 0) check_error(err,"Get channels not available"); #ifdef ALSAMM_DEBUG else if(sys_verbose) post("When setting channels count and got %d",*chs); #endif /* if buffersize is set use this instead buffertime */ if(alsamm_buffersize > 0){ #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: ask for max buffersize of %d samples", (unsigned int) alsamm_buffersize ); #endif alsamm_buffer_size = alsamm_buffersize; err = snd_pcm_hw_params_set_buffer_size_near(handle, params, (unsigned long *)&alsamm_buffer_size); if (err < 0) { check_error(err,"Unable to set max buffer size"); return err; } } else{ if(alsamm_buffertime <= 0) /* should never happen, but use 20ms */ alsamm_buffertime = 20000; #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: ask for max buffertime of %d ms", (unsigned int) (alsamm_buffertime*0.001) ); #endif err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &alsamm_buffertime, &dir); if (err < 0) { check_error(err,"Unable to set max buffer time"); return err; } } err = snd_pcm_hw_params_get_buffer_time(params, (unsigned int *)&alsamm_buffertime, &dir); if (err < 0) { check_error(err,"Unable to get buffer time"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: got buffertime to %f ms", (float) (alsamm_buffertime*0.001)); #endif err = snd_pcm_hw_params_get_buffer_size(params, (unsigned long *)&alsamm_buffer_size); if (err < 0) { check_error(err,"Unable to get buffer size"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("hw_params: got buffersize to %d samples",(int) alsamm_buffer_size); #endif err = snd_pcm_hw_params_get_period_size(params, (unsigned long *)&alsamm_period_size, &dir); if (err > 0) { check_error(err,"Unable to get period size"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Got period size of %d", (int) alsamm_period_size); #endif { unsigned int pmin,pmax; err = snd_pcm_hw_params_get_periods_min(params, &pmin, &dir); if (err > 0) { check_error(err,"Unable to get period size"); return err; } err = snd_pcm_hw_params_get_periods_min(params, &pmax, &dir); if (err > 0) { check_error(err,"Unable to get period size"); return err; } /* use maximum of periods */ if( alsamm_periods <= 0) alsamm_periods = pmax; alsamm_periods = (alsamm_periods > pmax)?pmax:alsamm_periods; alsamm_periods = (alsamm_periods < pmin)?pmin:alsamm_periods; err = snd_pcm_hw_params_set_periods(handle, params, alsamm_periods, dir); if (err > 0) { check_error(err,"Unable to set periods"); return err; } err = snd_pcm_hw_params_get_periods(params, &pmin, &dir); if (err > 0) { check_error(err,"Unable to get periods"); return err; } #ifdef ALSAMM_DEBUG if(sys_verbose) post("Got periods of %d, where periodsmin=%d, periodsmax=%d", alsamm_periods,pmin,pmax); #endif } /* write the parameters to device */ err = snd_pcm_hw_params(handle, params); if (err < 0) { check_error(err,"Unable to set hw params"); return err; } #endif /* ALSAAPI9 */ return 0; }
/** * Create and initialize Alsa audio output device with given parameters. * * @param Parameters - optional parameters * @throws AudioOutputException if output device cannot be opened */ AudioOutputDeviceAlsa::AudioOutputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters) : AudioOutputDevice(Parameters), Thread(true, true, 1, 0) { pcm_handle = NULL; stream = SND_PCM_STREAM_PLAYBACK; this->uiAlsaChannels = ((DeviceCreationParameterInt*)Parameters["CHANNELS"])->ValueAsInt(); this->uiSamplerate = ((DeviceCreationParameterInt*)Parameters["SAMPLERATE"])->ValueAsInt(); this->FragmentSize = ((DeviceCreationParameterInt*)Parameters["FRAGMENTSIZE"])->ValueAsInt(); uint Fragments = ((DeviceCreationParameterInt*)Parameters["FRAGMENTS"])->ValueAsInt(); String Card = ((DeviceCreationParameterString*)Parameters["CARD"])->ValueAsString(); dmsg(2,("Checking if hw parameters supported...\n")); if (HardwareParametersSupported(Card, uiAlsaChannels, uiSamplerate, Fragments, FragmentSize)) { pcm_name = "hw:" + Card; } else { fprintf(stderr, "Warning: your soundcard doesn't support chosen hardware parameters; "); fprintf(stderr, "trying to compensate support lack with plughw..."); fflush(stdout); pcm_name = "plughw:" + Card; } dmsg(2,("HW check completed.\n")); int err; snd_pcm_hw_params_alloca(&hwparams); // Allocate the snd_pcm_hw_params_t structure on the stack. /* Open PCM. The last parameter of this function is the mode. */ /* If this is set to 0, the standard mode is used. Possible */ /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */ /* If SND_PCM_NONBLOCK is used, read / write access to the */ /* PCM device will return immediately. If SND_PCM_ASYNC is */ /* specified, SIGIO will be emitted whenever a period has */ /* been completely processed by the soundcard. */ if ((err = snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0)) < 0) { throw AudioOutputException(String("Error opening PCM device ") + pcm_name + ": " + snd_strerror(err)); } if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) { throw AudioOutputException(String("Error, cannot initialize hardware parameter structure: ") + snd_strerror(err)); } /* Set access type. This can be either */ /* SND_PCM_ACCESS_RW_INTERLEAVED or */ /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */ if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { throw AudioOutputException(String("Error snd_pcm_hw_params_set_access: ") + snd_strerror(err)); } /* Set sample format */ #if WORDS_BIGENDIAN if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0) #else // little endian if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) #endif { throw AudioOutputException(String("Error setting sample format: ") + snd_strerror(err)); } int dir = 0; /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ #if ALSA_MAJOR > 0 if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &uiSamplerate, &dir)) < 0) #else if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, uiSamplerate, &dir)) < 0) #endif { throw AudioOutputException(String("Error setting sample rate: ") + snd_strerror(err)); } if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, uiAlsaChannels)) < 0) { throw AudioOutputException(String("Error setting number of channels: ") + snd_strerror(err)); } /* Set number of periods. Periods used to be called fragments. */ if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, Fragments, dir)) < 0) { throw AudioOutputException(String("Error setting number of ") + ToString(Fragments) + " periods: " + snd_strerror(err)); } /* Set buffer size (in frames). The resulting latency is given by */ /* latency = periodsize * periods / (rate * bytes_per_frame) */ if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (FragmentSize * Fragments))) < 0) { throw AudioOutputException(String("Error setting buffersize: ") + snd_strerror(err)); } /* Apply HW parameter settings to */ /* PCM device and prepare device */ if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { throw AudioOutputException(String("Error setting HW params: ") + snd_strerror(err)); } if (snd_pcm_sw_params_malloc(&swparams) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params_malloc: ") + snd_strerror(err)); } if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params_current: ") + snd_strerror(err)); } if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params_set_stop_threshold: ") + snd_strerror(err)); } if (snd_pcm_sw_params(pcm_handle, swparams) != 0) { throw AudioOutputException(String("Error in snd_pcm_sw_params: ") + snd_strerror(err)); } if ((err = snd_pcm_prepare(pcm_handle)) < 0) { throw AudioOutputException(String("Error snd_pcm_prepare: ") + snd_strerror(err)); } // allocate Alsa output buffer pAlsaOutputBuffer = new int16_t[uiAlsaChannels * FragmentSize]; // create audio channels for this audio device to which the sampler engines can write to for (int i = 0; i < uiAlsaChannels; i++) this->Channels.push_back(new AudioChannel(i, FragmentSize)); if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) { Play(); } }
int AlsaIO::Initialize(uint Channels, uint Samplerate, uint Fragments, uint FragmentSize, String Card) { this->uiChannels = Channels; this->uiSamplerate = Samplerate; this->uiMaxSamplesPerCycle = FragmentSize; this->bInterleaved = true; if (HardwareParametersSupported(Channels, Samplerate, Fragments, FragmentSize)) { pcm_name = "hw:" + Card; } else { printf("Warning: your soundcard doesn't support chosen hardware parameters; "); printf("trying to compensate support lack with plughw..."); fflush(stdout); pcm_name = "plughw:" + Card; } int err; snd_pcm_hw_params_alloca(&hwparams); // Allocate the snd_pcm_hw_params_t structure on the stack. /* Open PCM. The last parameter of this function is the mode. */ /* If this is set to 0, the standard mode is used. Possible */ /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */ /* If SND_PCM_NONBLOCK is used, read / write access to the */ /* PCM device will return immediately. If SND_PCM_ASYNC is */ /* specified, SIGIO will be emitted whenever a period has */ /* been completely processed by the soundcard. */ if ((err = snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0)) < 0) { fprintf(stderr, "Error opening PCM device %s: %s\n", pcm_name.c_str(), snd_strerror(err)); return -1; } if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) { fprintf(stderr, "Error, cannot initialize hardware parameter structure: %s.\n", snd_strerror(err)); return -1; } /* Set access type. This can be either */ /* SND_PCM_ACCESS_RW_INTERLEAVED or */ /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */ if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "Error snd_pcm_hw_params_set_access: %s.\n", snd_strerror(err)); return -1; } /* Set sample format */ #if WORDS_BIGENDIAN if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE)) < 0) { #else // little endian if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) { #endif fprintf(stderr, "Error setting sample format. : %s\n", snd_strerror(err)); return -1; } int dir = 0; /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ #if ALSA_MAJOR > 0 if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &Samplerate, &dir)) < 0) { #else if((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, Samplerate, &dir)) < 0) { #endif fprintf(stderr, "Error setting sample rate. : %s\n", snd_strerror(err)); return -1; } if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, Channels)) < 0) { fprintf(stderr, "Error setting number of channels. : %s\n", snd_strerror(err)); return -1; } /* Set number of periods. Periods used to be called fragments. */ if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, Fragments, dir)) < 0) { fprintf(stderr, "Error setting number of periods. : %s\n", snd_strerror(err)); return -1; } /* Set buffer size (in frames). The resulting latency is given by */ /* latency = periodsize * periods / (rate * bytes_per_frame) */ if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (FragmentSize * Fragments))) < 0) { fprintf(stderr, "Error setting buffersize. : %s\n", snd_strerror(err)); return -1; } /* Apply HW parameter settings to */ /* PCM device and prepare device */ if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { fprintf(stderr, "Error setting HW params. : %s\n", snd_strerror(err)); return -1; } if (snd_pcm_sw_params_malloc(&swparams) != 0) { fprintf(stderr, "Error in snd_pcm_sw_params_malloc. : %s\n", snd_strerror(err)); return -1; } if (snd_pcm_sw_params_current(pcm_handle, swparams) != 0) { fprintf(stderr, "Error in snd_pcm_sw_params_current. : %s\n", snd_strerror(err)); return -1; } if (snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xffffffff) != 0) { fprintf(stderr, "Error in snd_pcm_sw_params_set_stop_threshold. : %s\n", snd_strerror(err)); return -1; } if (snd_pcm_sw_params(pcm_handle, swparams) != 0) { fprintf(stderr, "Error in snd_pcm_sw_params. : %s\n", snd_strerror(err)); return -1; } if ((err = snd_pcm_prepare(pcm_handle)) < 0) { fprintf(stderr, "Error snd_pcm_prepare : %s\n", snd_strerror(err)); return -1; } // allocate the audio output buffer pOutputBuffer = new int16_t[Channels * FragmentSize]; this->bInitialized = true; return 0; } /** * Checks if sound card supports the chosen parameters. * * @returns true if hardware supports it */ bool AlsaIO::HardwareParametersSupported(uint channels, int samplerate, uint numfragments, uint fragmentsize) { pcm_name = "hw:0,0"; if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, 0) < 0) return false; snd_pcm_hw_params_alloca(&hwparams); if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { snd_pcm_close(pcm_handle); return false; } if (snd_pcm_hw_params_test_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { snd_pcm_close(pcm_handle); return false; } #if WORDS_BIGENDIAN if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_BE) < 0) { #else // little endian if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) { #endif snd_pcm_close(pcm_handle); return false; } int dir = 0; if (snd_pcm_hw_params_test_rate(pcm_handle, hwparams, samplerate, dir) < 0) { snd_pcm_close(pcm_handle); return false; } if (snd_pcm_hw_params_test_channels(pcm_handle, hwparams, channels) < 0) { snd_pcm_close(pcm_handle); return false; } if (snd_pcm_hw_params_test_periods(pcm_handle, hwparams, numfragments, dir) < 0) { snd_pcm_close(pcm_handle); return false; } if (snd_pcm_hw_params_test_buffer_size(pcm_handle, hwparams, (fragmentsize * numfragments)) < 0) { snd_pcm_close(pcm_handle); return false; } snd_pcm_close(pcm_handle); return true; } void AlsaIO::Activate() { this->StartThread(); } int AlsaIO::Main() { if (!pEngine) { fprintf(stderr, "AlsaIO: No Sampler Engine assigned, exiting.\n"); exit(EXIT_FAILURE); } if (!bInitialized) { fprintf(stderr, "AlsaIO: Not yet intitialized, exiting.\n"); exit(EXIT_FAILURE); } while (true) { // let the engine render audio for the current audio fragment pEngine->RenderAudio(uiMaxSamplesPerCycle); // check clipping in the audio sum, convert to sample_type // (from 32bit to 16bit sample) and copy to output buffer float sample_point; uint o = 0; for (uint s = 0; s < uiMaxSamplesPerCycle; s++) { for (uint c = 0; c < uiChannels; c++) { sample_point = pEngine->GetAudioSumBuffer(c)[s] * pEngine->Volume; if (sample_point < -32768.0) sample_point = -32768.0; if (sample_point > 32767.0) sample_point = 32767.0; this->pOutputBuffer[o++] = (int32_t) sample_point; } } // output sound int res = Output(); if (res < 0) { fprintf(stderr, "AlsaIO: Audio output error, exiting.\n"); exit(EXIT_FAILURE); } } } /** * Will be called after every audio fragment cycle, to output the audio data * of the current fragment to the soundcard. * * @returns 0 on success */ int AlsaIO::Output() { int err = snd_pcm_writei(pcm_handle, pOutputBuffer, uiMaxSamplesPerCycle); if (err < 0) { fprintf(stderr, "Error snd_pcm_writei failed. : %s\n", snd_strerror(err)); return -1; } return 0; } void AlsaIO::Close() { if (bInitialized) { //dmsg(0,("Stopping Alsa Thread...")); //StopThread(); //FIXME: commented out due to a bug in thread.cpp (StopThread() doesn't return at all) //dmsg(0,("OK\n")); if (pcm_handle) { //FIXME: currently commented out due to segfault //snd_pcm_close(pcm_handle); pcm_handle = NULL; } if (pOutputBuffer) { //FIXME: currently commented out due to segfault //delete[] pOutputBuffer; pOutputBuffer = NULL; } bInitialized = false; } } void* AlsaIO::GetInterleavedOutputBuffer() { return pOutputBuffer; } void* AlsaIO::GetChannelOutputBufer(uint Channel) { fprintf(stderr, "AlsaIO::GetChannelOutputBufer(): Only interleaved access allowed so far, exiting.\n"); exit(EXIT_FAILURE); // just to avoid compiler warnings return NULL; }
static void* sound_thread(void* context) { struct SPU* c = (struct SPU*)context; int div; snd_pcm_t* snd; snd_pcm_hw_params_t* hwp; int rate = c->sampling; int periods = 3; snd_pcm_hw_params_alloca(&hwp); if (snd_pcm_open(&snd, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) { return NULL; } if (snd_pcm_hw_params_any(snd, hwp) < 0) { return NULL; } div = c->bit / 8; switch (c->bit) { case 8: if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_U8) < 0) { return NULL; } break; case 16: if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_S16_LE) < 0) { return NULL; } break; case 24: if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_S24_LE) < 0) { return NULL; } break; case 32: if (snd_pcm_hw_params_set_format(snd, hwp, SND_PCM_FORMAT_S32_LE) < 0) { return NULL; } break; default: return NULL; } if (snd_pcm_hw_params_set_rate_near(snd, hwp, &rate, 0) < 0) { return NULL; } if (rate != SAMPLE_RATE) { return NULL; } if (snd_pcm_hw_params_set_channels(snd, hwp, c->ch) < 0) { return NULL; } if (snd_pcm_hw_params_set_periods(snd, hwp, periods, 0) < 0) { return NULL; } if (snd_pcm_hw_params_set_buffer_size(snd, hwp, (periods * c->size) / 4) < 0) { return NULL; } if (snd_pcm_hw_params(snd, hwp) < 0) { return NULL; } while (c->alive) { c->callback(c->buffer, c->size); while (c->alive) { if (snd_pcm_writei(snd, c->buffer, c->size / div) < 0) { snd_pcm_prepare(snd); } else { break; } } } snd_pcm_drain(snd); snd_pcm_close(snd); return NULL; }
void PCMThread::init() { snd_pcm_t* pcm_handle; snd_pcm_hw_params_t* hwparams; snd_pcm_uframes_t buffersize_return; unsigned int tmp; int err; std::unique_ptr<PCMHandle> spPCMHandle {new PCMHandle {spSettings_->pcmName_, SND_PCM_STREAM_CAPTURE}}; QObject::connect (spPCMHandle.get(), &PCMThread::PCMHandle::sigDebug, this, &PCMThread::slotDebug); snd_pcm_hw_params_alloca (&hwparams); if ( (err = snd_pcm_hw_params_any (*spPCMHandle, hwparams)) < 0) throw std::runtime_error (snd_strerror (err)); if ( (err = snd_pcm_hw_params_set_access (*spPCMHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) throw std::runtime_error (snd_strerror (err)); if ( (err = snd_pcm_hw_params_set_format (*spPCMHandle, hwparams, SND_PCM_FORMAT_FLOAT)) < 0) throw std::runtime_error (snd_strerror (err)); tmp = spSettings_->rate_; if ( (err = snd_pcm_hw_params_set_rate_near (*spPCMHandle, hwparams, &tmp, 0)) < 0) throw std::runtime_error (snd_strerror (err)); tmp = spSettings_->channels_; if ( (err = snd_pcm_hw_params_set_channels (*spPCMHandle, hwparams, tmp)) < 0) throw std::runtime_error (snd_strerror (err)); tmp = spSettings_->periods_; if ( (err = snd_pcm_hw_params_set_periods (*spPCMHandle, hwparams, tmp, 0)) < 0) throw std::runtime_error (snd_strerror (err)); buffersize_return = spSettings_->periodSize_ * spSettings_->periods_; if ( (err = snd_pcm_hw_params_set_buffer_size_near (*spPCMHandle, hwparams, &buffersize_return)) < 0) throw std::runtime_error (snd_strerror (err)); if (buffersize_return != static_cast<snd_pcm_uframes_t> (spSettings_->periodSize_ * spSettings_->periods_)) { DebugHelper dbgHelper; dbgHelper << "Period size " << spSettings_->periodSize_ << " not available, using " << buffersize_return / spSettings_->periods_; emit sigDebug (dbgHelper.string()); periodSize_ = buffersize_return / spSettings_->periods_; } else { periodSize_ = spSettings_->periodSize_; } if ( (err = snd_pcm_hw_params (*spPCMHandle, hwparams)) < 0) throw std::runtime_error (snd_strerror (err)); spPCMHandle_ = std::move (spPCMHandle); emit sigDebug ("Initialized : " + QString::fromStdString (spSettings_->pcmName_)); }
static void Wav_handler(Instance *pi, void *data) { ALSAio_private *priv = (ALSAio_private *)pi; Wav_buffer *wav_in = data; int state; int dir = 0; int rc; //int i; snd_pcm_sframes_t n; if (!priv->c.enable) { return; } if (!priv->c.rate) { /* Set rate. */ char channels[32]; char rate[32]; sprintf(rate, "%d", wav_in->params.rate); set_rate(pi, rate); /* Set channels. */ sprintf(channels, "%d", wav_in->params.channels); set_channels(pi, channels); /* Set format */ snd_pcm_format_t format = ALSAio_bps_to_snd_fmt(wav_in->params.bits_per_sample); if (format != SND_PCM_FORMAT_UNKNOWN) { priv->c.format = format; rc = snd_pcm_hw_params_set_format(priv->c.handle, priv->c.hwparams, priv->c.format); if (rc < 0) { fprintf(stderr, "*** %s: snd_pcm_hw_params_set_format %s: %s\n", __func__, s(priv->c.device), snd_strerror(rc)); } } } state = snd_pcm_state(priv->c.handle); dpf("%s: state(1)=%s\n", __func__, ALSAio_state_to_string(state)); if (state == SND_PCM_STATE_OPEN || state == SND_PCM_STATE_SETUP) { /* One time playback setup. */ /* FIXME: Why does 64 work on NVidia CK804 with "snd_intel8x0" driver, but not 32, 128, 2048? How to find out what will work? */ snd_pcm_uframes_t frames = priv->c.frames_per_io; fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); rc = snd_pcm_hw_params_set_period_size_near(priv->c.handle, priv->c.hwparams, &frames, &dir); fprintf(stderr, "set_period_size_near returns %d (frames=%d)\n", rc, (int)frames); int periods = 4; rc = snd_pcm_hw_params_set_periods(priv->c.handle, priv->c.hwparams, periods, 0); if (rc < 0) { fprintf(stderr, "*** snd_pcm_hw_params_set_periods %s: %s\n", s(priv->c.device), snd_strerror(rc)); } rc = snd_pcm_hw_params(priv->c.handle, priv->c.hwparams); if (rc < 0) { fprintf(stderr, "*** snd_pcm_hw_params %s: %s\n", s(priv->c.device), snd_strerror(rc)); } state = snd_pcm_state(priv->c.handle); fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); rc = snd_pcm_prepare(priv->c.handle); state = snd_pcm_state(priv->c.handle); fprintf(stderr, "%s: state=%s\n", __func__, ALSAio_state_to_string(state)); } dpf("%s: state(2)=%s\n", __func__, ALSAio_state_to_string(state)); int out_frames = wav_in->data_length / (priv->c.channels * priv->c.format_bytes); int frames_written = 0; while (1) { n = snd_pcm_writei(priv->c.handle, (uint8_t*)wav_in->data + (frames_written * (priv->c.channels * priv->c.format_bytes)), out_frames); if (n > 0) { out_frames -= n; frames_written += n; } else { break; } } if (n < 0) { fprintf(stderr, "*** snd_pcm_writei %s: %s\n", s(priv->c.device), snd_strerror((int)n)); fprintf(stderr, "*** attempting snd_pcm_prepare() to correct...\n"); snd_pcm_prepare(priv->c.handle); } if (wav_in->no_feedback == 0 /* The default is 0, set to 1 if "filler" code below is called. */ && pi->outputs[OUTPUT_FEEDBACK].destination) { Feedback_buffer *fb = Feedback_buffer_new(); fb->seq = wav_in->seq; PostData(fb, pi->outputs[OUTPUT_FEEDBACK].destination); } Wav_buffer_release(&wav_in); }
int AlsaAudioPlugin::init(shared_ptr<t_CPC> cpc, shared_ptr<t_PSG> psg) { if(!cpc->snd_enabled) { InfoLogMessage("[ALSA Audio Plugin] Not opening audio because disabled in the config"); return 0; } /* TODO */ unsigned int rate = cpc->snd_playback_rate; int channels = cpc->snd_stereo ? 2 : 1; snd_pcm_format_t format = SND_PCM_FORMAT_S16; switch(cpc->snd_bits) { case 8: format = SND_PCM_FORMAT_U8; break; case 16: format = SND_PCM_FORMAT_S16; break; case 24: format = SND_PCM_FORMAT_S24; break; case 32: format = SND_PCM_FORMAT_S32; break; default: WarningLogMessage("[ALSA Audio Plugin] Warning, %d bits format unknown, fallback to %s.", cpc->snd_bits, snd_pcm_format_name(format)); } int periods = 2; periodsize = 4096; unsigned int exact_rate; int dir, err; /* Handle for the PCM device */ //snd_pcm_t *pcm_handle; /* Playback stream */ snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; /* This structure contains information about */ /* the hardware and can be used to specify the */ /* configuration to be used for the PCM stream. */ snd_pcm_hw_params_t *hwparams; /* Name of the PCM device, like plughw:0,0 */ /* The first number is the number of the soundcard, */ /* the second number is the number of the device. */ char *pcm_name = strdup("plughw:0,0"); WarningLogMessage("TODO [%s:%d]: pcm_name need to be configurable.", __FILE__, __LINE__); /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&hwparams); /* Open PCM. The last parameter of this function is the mode. */ /* If this is set to 0, the standard mode is used. Possible */ /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. */ /* If SND_PCM_NONBLOCK is used, read / write access to the */ /* PCM device will return immediately. If SND_PCM_ASYNC is */ /* specified, SIGIO will be emitted whenever a period has */ /* been completely processed by the soundcard. */ if(err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error opening PCM device %s (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Init hwparams with full configuration space */ if(err = snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Can not configure PCM device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Set access type. This can be either */ /* SND_PCM_ACCESS_RW_INTERLEAVED or */ /* SND_PCM_ACCESS_RW_NONINTERLEAVED. */ /* There are also access types for MMAPed */ /* access, but this is beyond the scope */ /* of this introduction. */ if(err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting access on device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } /* Set sample format */ if(err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting format %s on device %s. (Error: %s)", snd_pcm_format_name(format), pcm_name, snd_strerror(err)); return 1; } /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ #if 0 // Segfault... Humf... TODO exact_rate = rate; if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, &dir) < 0) { ErrorLogMessage("Error setting rate (%d) on device %s.", rate, pcm_name); } if(dir != 0) { WarningLogMessage("The rate %d Hz is not supported by your hardware on device %s.\n" \ "==> Using %d Hz instead.", pcm_name, rate, exact_rate); } #else exact_rate = rate; if(err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, exact_rate, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting rate (%d) on device %s. (Error: %s)", rate, pcm_name, snd_strerror(err)); } #endif /* Set number of channels */ if(err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting channels (%d) on device %s. (Error: %s)", channels, pcm_name, snd_strerror(err)); return 1; } /* Set number of periods. Periods used to be called fragments. */ if(err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting periods (%d) on device %s. (Error: %s)", periods, pcm_name, snd_strerror(err)); return 1; } /* Set buffer size (in frames). The resulting latency is given by */ /* latency = periodsize * periods / (rate * bytes_per_frame) */ int buffer_size = (periodsize * periods) >> 2; if(err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, buffer_size) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting buffersize (%d) on device %s. (Error: %s)", buffer_size, pcm_name, snd_strerror(err)); return 1; } /* Apply HW parameter settings to */ /* PCM device and prepare device */ if(err = snd_pcm_hw_params(pcm_handle, hwparams) < 0) { ErrorLogMessage("[ALSA Audio Plugin] Error setting HW params on device %s. (Error: %s)", pcm_name, snd_strerror(err)); return 1; } sndBuffer = new uint8_t[periodsize*4*2]; if(!sndBuffer) { ErrorLogMessage("[ALSA Audio Plugin] sndBuffer allocation error."); return 1; } sndBufferPtr = sndBuffer; InfoLogMessage("[ALSA Audio Plugin] PCM device %s open at %d Hz %s, %d channels.", pcm_name, rate, snd_pcm_format_name(format), channels); return 0; }
AlsaDevice *alsa_device_open(char *device_name, unsigned int rate, int channels, int period) { int dir; int err; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; snd_pcm_uframes_t period_size = period; snd_pcm_uframes_t buffer_size = PERIODS*period; static snd_output_t *jcd_out; AlsaDevice *dev = malloc(sizeof(*dev)); if (!dev) return NULL; dev->device_name = malloc(1+strlen(device_name)); if (!dev->device_name) { free(dev); return NULL; } strcpy(dev->device_name, device_name); dev->channels = channels; dev->period = period; err = snd_output_stdio_attach(&jcd_out, stdout, 0); if ((err = snd_pcm_open (&dev->capture_handle, dev->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", dev->device_name, snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_any (dev->capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_access (dev->capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_format (dev->capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_rate_near (dev->capture_handle, hw_params, &rate, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); assert(0); } /*fprintf (stderr, "rate = %d\n", rate);*/ if ((err = snd_pcm_hw_params_set_channels (dev->capture_handle, hw_params, channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); assert(0); } period_size = period; dir = 0; if ((err = snd_pcm_hw_params_set_period_size_near (dev->capture_handle, hw_params, &period_size, &dir)) < 0) { fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_periods (dev->capture_handle, hw_params, PERIODS, 0)) < 0) { fprintf (stderr, "cannot set number of periods (%s)\n", snd_strerror (err)); assert(0); } buffer_size = period_size * PERIODS; dir=0; if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->capture_handle, hw_params, &buffer_size)) < 0) { fprintf (stderr, "cannot set buffer time (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params (dev->capture_handle, hw_params)) < 0) { fprintf (stderr, "cannot set capture parameters (%s)\n", snd_strerror (err)); assert(0); } /*snd_pcm_dump_setup(dev->capture_handle, jcd_out);*/ snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_current (dev->capture_handle, sw_params)) < 0) { fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_set_avail_min (dev->capture_handle, sw_params, period)) < 0) { fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params (dev->capture_handle, sw_params)) < 0) { fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_open (&dev->playback_handle, dev->device_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", dev->device_name, snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_any (dev->playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_access (dev->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_format (dev->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_rate_near (dev->playback_handle, hw_params, &rate, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); assert(0); } /*fprintf (stderr, "rate = %d\n", rate);*/ if ((err = snd_pcm_hw_params_set_channels (dev->playback_handle, hw_params, channels)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); assert(0); } period_size = period; dir = 0; if ((err = snd_pcm_hw_params_set_period_size_near (dev->playback_handle, hw_params, &period_size, &dir)) < 0) { fprintf (stderr, "cannot set period size (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params_set_periods (dev->playback_handle, hw_params, PERIODS, 0)) < 0) { fprintf (stderr, "cannot set number of periods (%s)\n", snd_strerror (err)); assert(0); } buffer_size = period_size * PERIODS; dir=0; if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->playback_handle, hw_params, &buffer_size)) < 0) { fprintf (stderr, "cannot set buffer time (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_hw_params (dev->playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot set playback parameters (%s)\n", snd_strerror (err)); assert(0); } /*snd_pcm_dump_setup(dev->playback_handle, jcd_out);*/ snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) { fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_current (dev->playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_set_avail_min (dev->playback_handle, sw_params, period)) < 0) { fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params_set_start_threshold (dev->playback_handle, sw_params, period)) < 0) { fprintf (stderr, "cannot set start mode (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_sw_params (dev->playback_handle, sw_params)) < 0) { fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (err)); assert(0); } snd_pcm_link(dev->capture_handle, dev->playback_handle); if ((err = snd_pcm_prepare (dev->capture_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); assert(0); } if ((err = snd_pcm_prepare (dev->playback_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); assert(0); } dev->readN = snd_pcm_poll_descriptors_count(dev->capture_handle); dev->writeN = snd_pcm_poll_descriptors_count(dev->playback_handle); dev->read_fd = malloc(dev->readN*sizeof(*dev->read_fd)); /*printf ("descriptors: %d %d\n", dev->readN, dev->writeN);*/ if (snd_pcm_poll_descriptors(dev->capture_handle, dev->read_fd, dev->readN) != dev->readN) { fprintf (stderr, "cannot obtain capture file descriptors (%s)\n", snd_strerror (err)); assert(0); } dev->write_fd = malloc(dev->writeN*sizeof(*dev->read_fd)); if (snd_pcm_poll_descriptors(dev->playback_handle, dev->write_fd, dev->writeN) != dev->writeN) { fprintf (stderr, "cannot obtain playback file descriptors (%s)\n", snd_strerror (err)); assert(0); } return dev; }
int main(void) { /* Handle for the PCM device */ snd_pcm_t *pcm_handle = NULL; /* Playback stream */ snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; /* This structure contains information about * the hardware and can be used to specify the * configuration to be used for the PCM stream. */ snd_pcm_hw_params_t *hwparams; /* Name of the PCM device, like plughw:0,0 * The first number is the number of the soundcard, * the second number is the number ot the device. */ char * pcm_name; /* Init pcm_name. Of course, later you * will make this configurable; */ pcm_name = strdup("plughw:0,0"); /* Allocate the snd_pcm_hw_params_t structure on the stack.*/ snd_pcm_hw_params_alloca(&hwparams); /* Open PCM. the last parameter of this function is the mode. * If this is set to 0, the standard mode is used. Possible * other values are SND_PCM_NONBLOCK AND SND_PCM_ASYNC. * if SND_PCM_NONBLOCK is used, read/write access to the * PCM device will return immediately. If SND_PCM_ASYNC is * specified. SIGIO will be emitted whenever a period has * been completely processed by the soundcard. */ if(snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0){ fprintf(stderr, "Error opening PCM device %s\n", pcm_name); return (-1); } /* Init hwparams with full configuration space */ if(snd_pcm_hw_params_any(pcm_handle, hwparams) < 0){ fprintf(stderr, "Can not configure this PCM device.\n"); return (-1); } int rate = 44100; /* Sample rate */ int exact_rate; /* Sample rate returned by snd_pcm_hw_params_set_rate_near */ int dir; /* exact_rate == rate --> dir = 0 */ /* exact_rate < rate --> dir = -1 */ /* exact_rate > rate --> dir = 1 */ int periods = 2; /* Number of periods */ snd_pcm_uframes_t periodsize = 8192; /* Periodsize (bytes) */ /* Set access type. This can be either * SND_PCM_ACCESS_RW_INTERLEAVED or * SND_PCM_ACCESS_MMAP_NONINTERLEAVED. * There are also access types for MMAPed * access, but this is beyond the scope * of this introduction. */ if(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0){ fprintf(stderr, "Error setting access.\n"); return (-1); } /* Set sample format */ if(snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0){ fprintf(stderr, "Error setting format.\n"); return (-1); } /* Set sample rate. If the exact rate is not supported by the hardware, use nearest possbile rate. */ exact_rate = rate; if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0){ fprintf(stderr, "Error setting rate.\n"); return (-1); } if(rate != exact_rate){ fprintf(stderr, "The rate %d HZ is not supported by your hardware.\n ==> Using %d HZ instead.\n", rate, exact_rate); } /* Set number of channels */ if(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0){ fprintf(stderr, "Error setting channels. \n"); return (-1); } /* Set number of periods. Periods used to be called fragments. */ if(snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0){ fprintf(stderr, "Error setting periods.\n"); return (-1); } /* Set buffer size (in frames). The resulting latency is given by * latency = periodsize * periods / (rate * bytes_per_frame) */ if(snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize * periods) >> 2) < 0){ fprintf(stderr, "Error setting buffersize.\n"); return (-1); } /* Apply HW parameter settins to * PCM device and prepare device */ if(snd_pcm_hw_params(pcm_handle, hwparams) < 0){ fprintf(stderr, "Error setting HW params. \n"); return (-1); } #if 0 /* Write num_frames frames from buffer data to * the PCM device pointed to by pcm_handle. * Returns the number of frames actually written. */ snd_pcm_sframes_t snd_pcm_writei(pcm_handle, data, num_frames); #endif #if 0 /*Write num_frames frames from buffer data to * the PCM device pointed to by pcm_handle. * Returns the number of frames actually written. */ snd_pcm_sframes_t snd_pcm_writen(pcm_handle, data, num_frames); #endif unsigned char *data; int pcmreturn, l1, l2; short s1, s2; int frames; int num_frames = 1024; data = (unsigned char *)malloc(periodsize); frames = periodsize >> 2; for(l1 = 0; l1 < 100; l1++){ for(l2 = 0; l2 < num_frames; l2++){ s1 = (l2 % 128) * 100 - 5000; s2 = (l2 % 256) * 100 - 5000; data[4*l2] = (unsigned char)s1; data[4*l2+1] = s1 >> 8; data[4*l2+2] = (unsigned char)s2; data[4*l2+3] = s2 >> 8; } while((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0){ snd_pcm_prepare(pcm_handle); fprintf(stderr, "<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>"); } } /* Stop PCM device and drop pending frames */ snd_pcm_drop(pcm_handle); /* Stop PCM device after pending frames have been played */ snd_pcm_drain(pcm_handle); return 0; }
int main(int argc, char *argv[]) { int err; struct sniffer_state sts; sts.pcm_name = strdup("plughw:0,0"); sts.stream = SND_PCM_STREAM_PLAYBACK; sts.format = SND_PCM_FORMAT_A_LAW; sts.rate = 8000; // sts.exact_rate; sts.periods = 2; sts.buffer_time = 25000; sts.period_time = 12500; snd_pcm_hw_params_alloca(&sts.hwparams); if (snd_pcm_open(&sts.pcm, sts.pcm_name, sts.stream, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", sts.pcm_name); return(-1); } if (snd_pcm_hw_params_any(sts.pcm, sts.hwparams) < 0) { fprintf(stderr, "Can not configure this PCM device.\n"); return(-1); } if (snd_pcm_hw_params_set_access(sts.pcm, sts.hwparams, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); return(-1); } if (snd_pcm_hw_params_set_format(sts.pcm, sts.hwparams, sts.format) < 0) { fprintf(stderr, "Error setting format.\n"); return(-1); } sts.exact_rate = sts.rate; if (snd_pcm_hw_params_set_rate_near(sts.pcm, sts.hwparams, &sts.exact_rate, 0) < 0) { fprintf(stderr, "Error setting rate.\n"); return(-1); } printf("rate: %d\n", sts.exact_rate); if (sts.rate != sts.exact_rate) { fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n" "==> Using %d Hz instead.\n", sts.rate, sts.exact_rate); } if (snd_pcm_hw_params_set_channels(sts.pcm, sts.hwparams, 1) < 0) { fprintf(stderr, "Error setting channels.\n"); return(-1); } if (snd_pcm_hw_params_set_periods(sts.pcm, sts.hwparams, sts.periods, 0) < 0) { fprintf(stderr, "Error setting periods.\n"); return(-1); } if (snd_pcm_hw_params_set_buffer_time_near(sts.pcm, sts.hwparams, &sts.buffer_time, &sts.dir) < 0) { fprintf(stderr, "Error setting buffersize.\n"); return(-1); } printf("buffer_time set to %d\n", sts.buffer_time); err = snd_pcm_hw_params_get_period_size(sts.hwparams, &sts.period_size, &sts.dir); if (err < 0) { printf("Unable to get period size for playback: %s\n", snd_strerror(err)); return err; } printf("period_size = %d\n", (int)sts.period_size); if (snd_pcm_hw_params(sts.pcm, sts.hwparams) < 0) { fprintf(stderr, "Error setting HW params.\n"); return(-1); } setvbuf(stdout, (char *)NULL, _IONBF, 0); int router_control_fd = open("/dev/visdn/router-control", O_RDWR); if (router_control_fd < 0) { perror("Unable to open router-control"); return 1; } int fd; fd = open("/dev/visdn/streamport", O_RDWR); if (fd < 0) { perror("cannot open /dev/visdn/streamport"); return 1; } struct vsp_ctl vsp_ctl; if (ioctl(fd, VISDN_SP_GET_NODEID, (caddr_t)&vsp_ctl) < 0) { perror("ioctl(VISDN_SP_GET_NODEID)"); return 1; } char node_id[80]; snprintf(node_id, sizeof(node_id), "/sys/%s", vsp_ctl.node_id); struct visdn_connect vc; memset(&vc, 0, sizeof(vc)); strncpy(vc.from_endpoint, argv[1], sizeof(vc.from_endpoint)); strncpy(vc.to_endpoint, node_id, sizeof(vc.to_endpoint)); printf("Connect: %s => %s\n", vc.from_endpoint, vc.to_endpoint); if (ioctl(router_control_fd, VISDN_IOC_CONNECT, (caddr_t) &vc) < 0) { perror("ioctl(VISDN_CONNECT, br=>sp)"); return 1; } int pipeline_id = vc.pipeline_id; memset(&vc, 0, sizeof(vc)); vc.pipeline_id = pipeline_id; if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_OPEN, (caddr_t)&vc) < 0) { perror("ioctl(VISDN_PIPELINE_OPEN, br=>sp)"); return 1; } memset(&vc, 0, sizeof(vc)); vc.pipeline_id = pipeline_id; if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_START, (caddr_t)&vc) < 0) { perror("ioctl(VISDN_PIPELINE_START, br=>sp)"); return 1; } //double phase = 0; const snd_pcm_channel_area_t *my_areas; snd_pcm_uframes_t offset, frames, size; snd_pcm_sframes_t avail, commitres; snd_pcm_state_t state; int first = 1; while (1) { state = snd_pcm_state(sts.pcm); if (state == SND_PCM_STATE_XRUN) { err = xrun_recovery(sts.pcm, -EPIPE); if (err < 0) { printf("XRUN recovery failed: %s\n", snd_strerror(err)); return err; } first = 1; } else if (state == SND_PCM_STATE_SUSPENDED) { err = xrun_recovery(sts.pcm, -ESTRPIPE); if (err < 0) { printf("SUSPEND recovery failed: %s\n", snd_strerror(err)); return err; } } avail = snd_pcm_avail_update(sts.pcm); if (avail < 0) { err = xrun_recovery(sts.pcm, avail); if (err < 0) { printf("avail update failed: %s\n", snd_strerror(err)); return err; } first = 1; continue; } if (avail < sts.period_size) { if (first) { first = 0; err = snd_pcm_start(sts.pcm); if (err < 0) { printf("Start error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } } else { err = snd_pcm_wait(sts.pcm, -1); if (err < 0) { if ((err = xrun_recovery(sts.pcm, err)) < 0) { printf("snd_pcm_wait error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } } continue; } size = sts.period_size; while (size > 0) { frames = size; err = snd_pcm_mmap_begin(sts.pcm, &my_areas, &offset, &frames); if (err < 0) { if ((err = xrun_recovery(sts.pcm, err)) < 0) { printf("MMAP begin avail error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } int r = read(fd, my_areas[0].addr + offset, frames); printf("%d %d %d: ", (int)offset, (int)frames, r); int i; for (i=0; i<r; i++) printf("%02x", *(__u8 *)(my_areas[0].addr + i)); printf("\n"); commitres = snd_pcm_mmap_commit(sts.pcm, offset, frames); if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { if ((err = xrun_recovery(sts.pcm, commitres >= 0 ? -EPIPE : commitres)) < 0) { printf("MMAP commit error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } size -= frames; } } return 0; }
int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access) { unsigned int rrate; int err, dir; printf("set_hwparams\n"); /* choose all parameters */ err = snd_pcm_hw_params_any(handle, params); if (err < 0) { printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); return err; } /* set the interleaved read/write format */ err = snd_pcm_hw_params_set_access(handle, params, access); if (err < 0) { printf("Access type not available for playback: %s\n", snd_strerror(err)); return err; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, params, format); if (err < 0) { printf("Sample format not available for playback: %s\n", snd_strerror(err)); return err; } /* set the count of channels */ err = snd_pcm_hw_params_set_channels(handle, params, channels); if (err < 0) { printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err)); return err; } /* set the stream rate */ rrate = rate; err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); if (err < 0) { printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); return err; } if (rrate != rate) { printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); return -EINVAL; } dir = 0; err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, &dir); if (err < 0) { printf("Unable to set period size %i for playback: %s\n", (int)period_size, snd_strerror(err)); return err; } err = snd_pcm_hw_params_set_periods(handle, params, periods, 0); if (err < 0) { printf("Unable to set periods %i for playback: %s\n", periods, snd_strerror(err)); return err; } /* write the parameters to device */ err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to set hw params for playback: %s\n", snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_periods(params, &periods, &dir); if (err < 0) { printf("Unable to get periods for playback: %s\n", snd_strerror(err)); return err; } err = snd_pcm_hw_params_get_period_size(params, &period_size, &dir); if (err < 0) { printf("Unable to get period size for playback: %s\n", snd_strerror(err)); return err; } return 0; }
int audioStreamer_ALSA::Open(char *devname, int is_write, int srate, int nch, int bps, int fragsize, int nfrags, int dosleep) { m_sleep=dosleep; /* Playback stream */ snd_pcm_stream_t stream = is_write?SND_PCM_STREAM_PLAYBACK:SND_PCM_STREAM_CAPTURE; /* This structure contains information about */ /* the hardware and can be used to specify the */ /* configuration to be used for the PCM stream. */ snd_pcm_hw_params_t *hwparams; /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&hwparams); if (snd_pcm_open(&pcm_handle, devname, stream, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", devname); return(-1); } /* Init hwparams with full configuration space */ if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { fprintf(stderr, "Can not configure this PCM device.\n"); return(-1); } if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); return(-1); } /* Set sample format */ m_bps=bps==32?32:bps==24?24:16; if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, bps==32?SND_PCM_FORMAT_S32_LE:bps==24?SND_PCM_FORMAT_S24_3LE:SND_PCM_FORMAT_S16_LE) < 0) { fprintf(stderr, "Error setting format.\n"); fprintf(stderr, "Try -bps 16, -bps 24, or -bps 32\n"); return(-1); } int dir=0; /* exact_rate == rate --> dir = 0 */ /* exact_rate < rate --> dir = -1 */ /* exact_rate > rate --> dir = 1 */ unsigned int usrate=srate; /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ m_srate=srate; int exact_rate = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &usrate, &dir); if (dir != 0) { fprintf(stderr, "The rate %d Hz is not supported by your hardware. Using %d Hz instead.\n", srate, exact_rate); m_srate=exact_rate; } /* Set number of channels */ if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, nch) < 0) { fprintf(stderr, "Error setting channels.\n"); fprintf(stderr, "Try -nch 1 or -nch 2\n"); return(-1); } m_nch=nch; int periods=m_nfrags=(is_write?nfrags:nfrags*3); int periodsize=fragsize; /* Set number of periods. Periods used to be called fragments. */ if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) { fprintf(stderr, "Error setting periods.\n"); fprintf(stderr, "Try -nbufs 2 through -nbufs 16\n"); return(-1); } /* Set buffer size (in frames). The resulting latency is given by */ /* latency = periodsize * periods / (rate * bytes_per_frame) */ if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, m_bufsize = (periodsize * periods)/(m_nch * m_bps/8)) < 0) { fprintf(stderr, "Error setting buffersize.\n"); fprintf(stderr, "Try -bufsize 256 through -bufsize 2048\n"); return(-1); } /* Apply HW parameter settings to */ /* PCM device and prepare device */ if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) { fprintf(stderr, "Error setting HW params.\n"); return(-1); } return 0; }
/* Initialise audio devices. */ int digi_init() { int err, tmp; char *device = "plughw:0,0"; snd_pcm_hw_params_t *params; pthread_attr_t attr; pthread_mutexattr_t mutexattr; //added on 980905 by adb to init sound kill system memset(SampleHandles, 255, sizeof(SampleHandles)); //end edit by adb /* Open the ALSA sound device */ if ((err = snd_pcm_open(&snd_devhandle,device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { con_printf(CON_CRITICAL, "open failed: %s\n", snd_strerror( err )); return -1; } snd_pcm_hw_params_alloca(¶ms); err = snd_pcm_hw_params_any(snd_devhandle, params); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_access(snd_devhandle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_format(snd_devhandle, params, SND_PCM_FORMAT_U8); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_channels(snd_devhandle, params, 2); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } tmp = 11025; err = snd_pcm_hw_params_set_rate_near(snd_devhandle, params, &tmp, NULL); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } snd_pcm_hw_params_set_periods(snd_devhandle, params, 3, 0); snd_pcm_hw_params_set_buffer_size(snd_devhandle,params, (SOUND_BUFFER_SIZE*3)/2); err = snd_pcm_hw_params(snd_devhandle, params); if (err < 0) { con_printf(CON_CRITICAL,"ALSA: Error %s\n", snd_strerror(err)); return -1; } /* Start the mixer thread */ /* We really should check the results of these */ pthread_mutexattr_init(&mutexattr); pthread_mutex_init(&mutex,&mutexattr); pthread_mutexattr_destroy(&mutexattr); if (pthread_attr_init(&attr) != 0) { con_printf(CON_CRITICAL, "failed to init attr\n"); snd_pcm_close( snd_devhandle ); return -1; } pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_create(&thread_id,&attr,mixer_thread,NULL); pthread_attr_destroy(&attr); digi_initialised = 1; return 0; }
input_module_t *alsa_open_module(module_param_t *params) { input_module_t *mod = calloc(1, sizeof(input_module_t)); im_alsa_state *s; module_param_t *current; char *device = "plughw:0,0"; /* default device */ int format = AFMT_S16_LE; int channels, rate; int use_metadata = 1; /* Default to on */ unsigned int buffered_time; snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE; snd_pcm_hw_params_t *hwparams; int err; mod->type = ICES_INPUT_PCM; mod->subtype = INPUT_PCM_LE_16; mod->getdata = alsa_read; mod->handle_event = event_handler; mod->metadata_update = metadata_update; mod->internal = calloc(1, sizeof(im_alsa_state)); s = mod->internal; s->fd = NULL; /* Set it to something invalid, for now */ s->rate = 44100; /* Defaults */ s->channels = 2; thread_mutex_create(&s->metadatalock); current = params; while(current) { if(!strcmp(current->name, "rate")) s->rate = atoi(current->value); else if(!strcmp(current->name, "channels")) s->channels = atoi(current->value); else if(!strcmp(current->name, "device")) device = current->value; else if(!strcmp(current->name, "metadata")) use_metadata = atoi(current->value); else if(!strcmp(current->name, "metadatafilename")) ices_config->metadata_filename = current->value; else LOG_WARN1("Unknown parameter %s for alsa module", current->name); current = current->next; } snd_pcm_hw_params_alloca(&hwparams); if ((err = snd_pcm_open(&s->fd, device, stream, 0)) < 0) { LOG_ERROR2("Failed to open audio device %s: %s", device, snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_any(s->fd, hwparams)) < 0) { LOG_ERROR1("Failed to initialize hwparams: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_access(s->fd, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { LOG_ERROR1("Error setting access: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_format(s->fd, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) { LOG_ERROR1("Couldn't set sample format to SND_PCM_FORMAT_S16_LE: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_rate_near(s->fd, hwparams, &s->rate, 0)) < 0) { LOG_ERROR1("Error setting rate: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_channels(s->fd, hwparams, s->channels)) < 0) { LOG_ERROR1("Error setting channels: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params_set_periods(s->fd, hwparams, 2, 0)) < 0) { LOG_ERROR1("Error setting periods: %s", snd_strerror(err)); goto fail; } buffered_time = 500000; if ((err = snd_pcm_hw_params_set_buffer_time_near(s->fd, hwparams, &buffered_time, 0)) < 0) { LOG_ERROR1("Error setting buffersize: %s", snd_strerror(err)); goto fail; } if ((err = snd_pcm_hw_params(s->fd, hwparams)) < 0) { LOG_ERROR1("Error setting HW params: %s", snd_strerror(err)); goto fail; } /* We're done, and we didn't fail! */ LOG_INFO3("Opened audio device %s at %d channel(s), %d Hz", device, s->channels, s->rate); if(use_metadata) { if(ices_config->metadata_filename) thread_create("im_alsa-metadata", metadata_thread_signal, mod, 1); else thread_create("im_alsa-metadata", metadata_thread_stdin, mod, 1); LOG_INFO0("Started metadata update thread"); } return mod; fail: close_module(mod); /* safe, this checks for valid contents */ return NULL; }
main(int argc, char **argv){ snd_pcm_t *handle; snd_pcm_hw_params_t *params; snd_pcm_uframes_t frames; //the libsamplerate stuff SRC_DATA datastr;//holds the data(inpu and output),input frames used, output frames generated SRC_STATE *statestr;//holds the state int error; //the lbsndfile stuff, one keeps the header the other the data SF_INFO sfinf;//has all the info like total frames,samplerate, channels, mode SNDFILE *input = NULL; //buffers used in computation to pass to the playback function float *buffin = NULL;//float into the converter float *filein = NULL; float *flangebuffout = NULL;//float to traverse the array for getting flange effects float *flangebase = NULL;//float to fix the array for initialising the flange effects float *buffout = NULL;//float out of the converter short *final = NULL;//final array to write to snd card float fldelmax = 256; float flfreq = 1; float flgain = .5; int fltime = 0; int pcm, readcount, pcmrc, blah;//pcm is used for error checking the alsa stuff, pcmrc is used in the main loop float *eofin;//to point to the end of the file's raw data int tmp;//used to hold information that is printed in stdio int i = 0;//index for initialising the output DAC // float fldelmax, flgain, flfreq; // pointer for the file input if (argc != 3){ printf("Usage requires music file and src ratio, please try again\n\n"); return 0; } char *inputname = argv[1]; //int *filein = argv[1]; input = sf_open(inputname, SFM_READ, &sfinf); if (input == NULL){ printf("could not open file sorry \n\n"); return 0; } fprintf(stderr, "Channels : %d\n", sfinf.channels); fprintf(stderr, "Sample rate; %d\n", sfinf.samplerate); fprintf(stderr, "Sections: %d\n", sfinf.sections); fprintf(stderr, "Format: %d\n", sfinf.format); // fprintf(stderr, "Frame Count: %d\n", sfinf.frames); //fprintf(stderr, "size: %d\n", sizeof(short)); //open sndcard if ((filein = malloc(sizeof(float)*sfinf.channels*sfinf.frames)) == NULL) { printf("MAN YOU OUT OF MEM"); return 0; } blah = sf_readf_float(input, filein, sfinf.frames); buffin = filein; eofin = filein + (sfinf.frames)*sfinf.channels; if (pcm =snd_pcm_open(&handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0)< 0){ printf("Error: CANNOT OPEN PCM DEVICE\n"); } //allocate default parameters snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); //set parameters if (pcm = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)< 0){ printf("Cannot set interleaved mode\n"); } if (pcm = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)< 0){ printf("CANNOT SET FORMAT\n"); } if (pcm = snd_pcm_hw_params_set_channels(handle, params, sfinf.channels)< 0){ printf("CANNOT SET CHANNELS \n"); } if (pcm = snd_pcm_hw_params_set_rate(handle, params, sfinf.samplerate, 0)< 0){ printf("CANNOT SET SAMPLERATES \n"); } if (pcm = snd_pcm_hw_params_set_periods(handle, params,1024, 0) < 0){ printf("CANNOT SET PERIOD TO 128"); } //write parameters if (pcm = snd_pcm_hw_params(handle, params)< 0){ printf("CANNOT SET HARDWARE PARAMETERS\n"); } printf("PCm NAME: %s\n", snd_pcm_name(handle)); printf("PCM state: %s \n", snd_pcm_state_name(snd_pcm_state(handle))); snd_pcm_hw_params_get_channels(params, &tmp); printf("channels: %i\n", tmp); snd_pcm_hw_params_get_rate(params, &tmp, 0); printf("rate: %d \n", tmp); //find size of period on hardware snd_pcm_hw_params_get_period_size(params, &frames, 0); fprintf(stderr, "# frames in a period: %d\n", frames); //buffers on buffers (buffout for float output from sample rate conversion), (final for short array to write to pcm) and flangebse for the flanger stuff buffout = malloc(frames*sfinf.channels * sizeof(float));//frames final = malloc(frames*sfinf.channels * sizeof(short));//frames