/** * Checks if sound card supports the chosen parameters. * * @returns true if hardware supports it * @throws AudioOutputException - if device cannot be accessed */ bool AudioOutputDeviceAlsa::HardwareParametersSupported(String card, uint channels, int samplerate, uint numfragments, uint fragmentsize) throw (AudioOutputException) { pcm_name = "hw:" + card; int err; if ((err = snd_pcm_open(&pcm_handle, pcm_name.c_str(), stream, SND_PCM_NONBLOCK)) < 0) { throw AudioOutputException(String("Error opening PCM device ") + pcm_name + ": " + snd_strerror(err)); } 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; }
int main(int argc, char *argv[]) { const char *device_name = "hw"; snd_pcm_t *pcm; snd_pcm_hw_params_t *hw_params; unsigned int i; unsigned int min, max; int any_rate; int err; if (argc > 1) device_name = argv[1]; err = snd_pcm_open(&pcm, device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if (err < 0) { fprintf(stderr, "cannot open device '%s': %s\n", device_name, snd_strerror(err)); return 1; } snd_pcm_hw_params_alloca(&hw_params); err = snd_pcm_hw_params_any(pcm, hw_params); if (err < 0) { fprintf(stderr, "cannot get hardware parameters: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } printf("Device: %s (type: %s)\n", device_name, snd_pcm_type_name(snd_pcm_type(pcm))); printf("Access types:"); for (i = 0; i < ARRAY_SIZE(accesses); ++i) { if (!snd_pcm_hw_params_test_access(pcm, hw_params, accesses[i])) printf(" %s", snd_pcm_access_name(accesses[i])); } putchar('\n'); printf("Formats:"); for (i = 0; i < ARRAY_SIZE(formats); ++i) { if (!snd_pcm_hw_params_test_format(pcm, hw_params, formats[i])) printf(" %s", snd_pcm_format_name(formats[i])); } putchar('\n'); err = snd_pcm_hw_params_get_channels_min(hw_params, &min); if (err < 0) { fprintf(stderr, "cannot get minimum channels count: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } err = snd_pcm_hw_params_get_channels_max(hw_params, &max); if (err < 0) { fprintf(stderr, "cannot get maximum channels count: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } printf("Channels:"); for (i = min; i <= max; ++i) { if (!snd_pcm_hw_params_test_channels(pcm, hw_params, i)) printf(" %u", i); } putchar('\n'); err = snd_pcm_hw_params_get_rate_min(hw_params, &min, NULL); if (err < 0) { fprintf(stderr, "cannot get minimum rate: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } err = snd_pcm_hw_params_get_rate_max(hw_params, &max, NULL); if (err < 0) { fprintf(stderr, "cannot get maximum rate: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } printf("Sample rates:"); if (min == max) printf(" %u", min); else if (!snd_pcm_hw_params_test_rate(pcm, hw_params, min + 1, 0)) printf(" %u-%u", min, max); else { any_rate = 0; for (i = 0; i < ARRAY_SIZE(rates); ++i) { if (!snd_pcm_hw_params_test_rate(pcm, hw_params, rates[i], 0)) { any_rate = 1; printf(" %u", rates[i]); } } if (!any_rate) printf(" %u-%u", min, max); } putchar('\n'); err = snd_pcm_hw_params_get_period_time_min(hw_params, &min, NULL); if (err < 0) { fprintf(stderr, "cannot get minimum period time: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } err = snd_pcm_hw_params_get_period_time_max(hw_params, &max, NULL); if (err < 0) { fprintf(stderr, "cannot get maximum period time: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } printf("Interrupt interval: %u-%u us\n", min, max); err = snd_pcm_hw_params_get_buffer_time_min(hw_params, &min, NULL); if (err < 0) { fprintf(stderr, "cannot get minimum buffer time: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &max, NULL); if (err < 0) { fprintf(stderr, "cannot get maximum buffer time: %s\n", snd_strerror(err)); snd_pcm_close(pcm); return 1; } printf("Buffer size: %u-%u us\n", min, max); snd_pcm_close(pcm); return 0; }
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; }
bool AlsaSource::SetupHW () { bool result = false; bool rw_available = false; bool mmap_available = false; #if DEBUG bool debug = debug_flags & RUNTIME_DEBUG_AUDIO; #else bool debug = false; #endif snd_pcm_hw_params_t *params = NULL; snd_output_t *output = NULL; guint32 buffer_time = 100000; // request 0.1 seconds of buffer time. int err = 0; int dir = 0; unsigned int rate = GetSampleRate (); unsigned int actual_rate = rate; guint32 channels = GetChannels (); if (debug) { err = snd_output_stdio_attach (&output, stdout, 0); if (err < 0) LOG_AUDIO ("AlsaSource::SetupHW (): Could not create alsa output: %s\n", snd_strerror (err)); } err = snd_pcm_hw_params_malloc (¶ms); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (malloc): %s\n", snd_strerror (err)); return false; } // choose all parameters err = snd_pcm_hw_params_any (pcm, params); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (no configurations available): %s\n", snd_strerror (err)); goto cleanup; } if (debug && output != NULL) { LOG_AUDIO ("AlsaSource::SetupHW (): hw configurations:\n"); snd_pcm_hw_params_dump (params, output); } // enable software resampling err = snd_pcm_hw_params_set_rate_resample (pcm, params, 1); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (could not enable resampling): %s\n", snd_strerror (err)); goto cleanup; } // test for available transfer modes if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_MMAP)) { err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: RW access mode not supported (%s).\n", snd_strerror (err)); } else { rw_available = true; } } if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_RW)) { err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: MMAP access mode not supported (%s).\n", snd_strerror (err)); } else { mmap_available = true; } } if (mmap_available) { mmap = true; } else if (rw_available) { mmap = false; } else { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed, no available access mode\n"); goto cleanup; } LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: using %s access mode.\n", mmap ? "MMAP" : "RW"); // set transfer mode (mmap or rw in our case) err = snd_pcm_hw_params_set_access (pcm, params, mmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED : SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (access type not available for playback): %s\n", snd_strerror (err)); goto cleanup; } // set audio format switch (GetInputBytesPerSample ()) { case 1: // 8 bit audio err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16); SetOutputBytesPerSample (2); break; case 2: // 16 bit audio err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16); SetOutputBytesPerSample (2); break; case 3: // 24 bit audio // write as 32 bit audio, this is a lot easier to write to than 24 bit. err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S32); SetOutputBytesPerSample (4); break; default: LOG_AUDIO ("AlsaSource::SetupHW (): Invalid input bytes per sample, expected 1, 2 or 3, got %i\n", GetInputBytesPerSample ()); goto cleanup; } if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample format not available for playback): %s\n", snd_strerror (err)); goto cleanup; } // set channel count err = snd_pcm_hw_params_set_channels (pcm, params, channels); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (channels count %i not available for playback): %s\n", channels, snd_strerror (err)); goto cleanup; } // set sample rate err = snd_pcm_hw_params_set_rate_near (pcm, params, &actual_rate, 0); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback): %s\n", rate, snd_strerror (err)); goto cleanup; } else if (actual_rate != rate) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback, only got %i Hz).\n", rate, actual_rate); goto cleanup; } // set the buffer time err = snd_pcm_hw_params_set_buffer_time_near (pcm, params, &buffer_time, &dir); if (err < 0) { LOG_AUDIO ("AudioNode::SetupHW (): Audio HW setup failed (unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror (err)); goto cleanup; } // write the parameters to device err = snd_pcm_hw_params (pcm, params); if (err < 0) { LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (unable to set hw params for playback: %s)\n", snd_strerror (err)); if (debug && output != NULL) { LOG_AUDIO ("AlsaSource::SetupHW (): current hw configurations:\n"); snd_pcm_hw_params_dump (params, output); } goto cleanup; } if (debug) { LOG_AUDIO ("AlsaSource::SetupHW (): hardware pause support: %s\n", snd_pcm_hw_params_can_pause (params) == 0 ? "no" : "yes"); LOG_AUDIO ("AlsaSource::SetupHW (): succeeded\n"); if (output != NULL) snd_pcm_hw_params_dump (params, output); } result = true; cleanup: snd_pcm_hw_params_free (params); return result; }
bool DevAlsa::start(QString *err) { #ifdef ALSA snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams; int dir; int aerr; pthread_attr_t pthread_attr; if(snd_pcm_open(&alsa_pcm,alsa_device.toUtf8(), SND_PCM_STREAM_PLAYBACK,0)!=0) { *err=tr("unable to open ALSA device")+" \""+alsa_device+"\""; return false; } snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_any(alsa_pcm,hwparams); // // Access Type // if(snd_pcm_hw_params_test_access(alsa_pcm,hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)<0) { *err=tr("interleaved access not supported"); return false; } snd_pcm_hw_params_set_access(alsa_pcm,hwparams,SND_PCM_ACCESS_RW_INTERLEAVED); // // Sample Format // if(snd_pcm_hw_params_set_format(alsa_pcm,hwparams, SND_PCM_FORMAT_S32_LE)==0) { alsa_format=AudioDevice::S32_LE; if(global_log_verbose) { Log(LOG_INFO,"using ALSA S32_LE sample format"); } } else { if(snd_pcm_hw_params_set_format(alsa_pcm,hwparams, SND_PCM_FORMAT_S16_LE)==0) { alsa_format=AudioDevice::S16_LE; if(global_log_verbose) { Log(LOG_INFO,"using ALSA S16_LE sample format"); } } else { *err=tr("incompatible sample format"); return false; } } // // Sample Rate // alsa_samplerate=codec()->samplerate(); snd_pcm_hw_params_set_rate_near(alsa_pcm,hwparams,&alsa_samplerate,&dir); if(alsa_samplerate!=codec()->samplerate()) { if(global_log_verbose) { Log(LOG_INFO, QString().sprintf("using ALSA sample rate of %u samples/sec", alsa_samplerate)); } } // // Channels // alsa_channels=codec()->channels(); snd_pcm_hw_params_set_channels_near(alsa_pcm,hwparams,&alsa_channels); if(alsa_channels!=codec()->channels()) { if(global_log_verbose) { Log(LOG_INFO, QString().sprintf("using ALSA channel count of %u",alsa_channels)); } } // // Buffer Parameters // alsa_period_quantity=ALSA_PERIOD_QUANTITY; snd_pcm_hw_params_set_periods_near(alsa_pcm,hwparams,&alsa_period_quantity, &dir); if(alsa_period_quantity!=ALSA_PERIOD_QUANTITY) { if(global_log_verbose) { Log(LOG_INFO, QString().sprintf("using ALSA period quantity of %u", alsa_period_quantity)); } } alsa_buffer_size=alsa_samplerate/2; snd_pcm_hw_params_set_buffer_size_near(alsa_pcm,hwparams,&alsa_buffer_size); if(alsa_buffer_size!=(alsa_samplerate/2)) { if(global_log_verbose) { Log(LOG_INFO, QString().sprintf("using ALSA buffer size of %lu frames", alsa_buffer_size)); } } // // Fire It Up // if((aerr=snd_pcm_hw_params(alsa_pcm,hwparams))<0) { *err=tr("ALSA device error 1")+": "+snd_strerror(aerr); return false; } alsa_pcm_buffer=new float[alsa_buffer_size*alsa_channels]; // // Set Wake-up Timing // snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(alsa_pcm,swparams); snd_pcm_sw_params_set_avail_min(alsa_pcm,swparams,alsa_buffer_size/2); if((aerr=snd_pcm_sw_params(alsa_pcm,swparams))<0) { *err=tr("ALSA device error 2")+": "+snd_strerror(aerr); return false; } // // Start the Callback // pthread_attr_init(&pthread_attr); // if(use_realtime) { // pthread_attr_setschedpolicy(&pthread_attr,SCHED_FIFO); pthread_create(&alsa_pthread,&pthread_attr,AlsaCallback,this); // alsa_meter_timer->start(AUDIO_METER_INTERVAL); alsa_play_position_timer->start(50); alsa_meter_timer->start(AUDIO_METER_INTERVAL); return true; #else return false; #endif // ALSA }