// // Set up both the audio and video capturing on the card // void an_configure_capture_card( void ) { struct v4l2_cropcap cropcap; struct v4l2_crop crop; struct v4l2_format fmt; sys_config info; int input; u32 pix_fmt; dvb_config_get( &info ); CLEAR(cropcap); CLEAR(crop); CLEAR(fmt); m_width = PAL_WIDTH_CAPTURE; m_height = PAL_HEIGHT_CAPTURE; // Set the cropping, ignore any errors cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(m_i_fd, VIDIOC_CROPCAP, &cropcap)==0) { crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; /* reset to default */ ioctl(m_i_fd, VIDIOC_S_CROP, &crop); } // // Analogue Video capture // pix_fmt = V4L2_PIX_FMT_YUV420; m_sws = NULL; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = m_width; fmt.fmt.pix.height = m_height; fmt.fmt.pix.pixelformat = pix_fmt; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (ioctl(m_i_fd, VIDIOC_S_FMT, &fmt) == 0) { an_set_image_size( AV_PIX_FMT_YUV420P ); } else { pix_fmt = V4L2_PIX_FMT_YUYV; // capture format fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = m_width; fmt.fmt.pix.height = m_height; fmt.fmt.pix.pixelformat = pix_fmt; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (ioctl(m_i_fd, VIDIOC_S_FMT, &fmt) == 0) { // Format conversion will be required m_sws = sws_getContext( m_width, m_height, AV_PIX_FMT_YUYV422, m_width, m_height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL,NULL, NULL); an_set_image_size( AV_PIX_FMT_YUYV422 ); } else { logger("CAP ANALOGUE FORMAT NOT SUPPORTED"); } } if(ioctl(m_i_fd, VIDIOC_G_FMT, &fmt)<0 ) logger("can't get format"); // input = V4L2_INPUT_TYPE_CAMERA; input = info.video_capture_device_input; if( ioctl( m_i_fd, VIDIOC_S_INPUT, &input) < 0 ) { loggerf("CAP Error VIDIOC_S_INPUT %d",input); } /* v4l2_streamparm parm; memset(&parm,0,sizeof(v4l2_streamparm)); parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; parm.parm.capture.capturemode = 0; parm.parm.capture.readbuffers = 0; if( ioctl( m_i_fd, VIDIOC_S_PARM, &parm) < 0 ) { loggerf("CAP Error VIDIOC_S_PARM"); } */ info.video_bitrate = calculate_video_bitrate(); // // Analogue sound capture // snd_pcm_hw_params_t *hw_params; if(snd_pcm_open(&m_audio_handle, "pulse", SND_PCM_STREAM_CAPTURE, 0)< 0 ) { loggerf("Unable to open sound device"); return; } unsigned int rate = 48000; int r; r = snd_pcm_hw_params_malloc(&hw_params); r = snd_pcm_hw_params_any(m_audio_handle, hw_params); r = snd_pcm_hw_params_set_access(m_audio_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); r = snd_pcm_hw_params_set_format(m_audio_handle, hw_params, SND_PCM_FORMAT_S16_LE); r = snd_pcm_hw_params_set_rate_near(m_audio_handle, hw_params, &rate, 0); r = snd_pcm_hw_params_set_channels(m_audio_handle, hw_params, 2); r = snd_pcm_hw_params(m_audio_handle, hw_params); snd_pcm_hw_params_free(hw_params); r = snd_pcm_prepare(m_audio_handle); an_init_codecs(); m_capturing = true; an_setup_video_capturing( m_i_fd ); an_setup_audio_capturing(); }
static RD_BOOL alsa_set_format(snd_pcm_t * pcm, RD_WAVEFORMATEX * pwfx) { snd_pcm_hw_params_t *hwparams = NULL; int err; unsigned int buffertime; short samplewidth; int audiochannels; unsigned int rate; samplewidth = pwfx->wBitsPerSample / 8; if ((err = snd_pcm_hw_params_malloc(&hwparams)) < 0) { error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err)); return False; } if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0) { error("snd_pcm_hw_params_any: %s\n", snd_strerror(err)); return False; } if ((err = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { error("snd_pcm_hw_params_set_access: %s\n", snd_strerror(err)); return False; } if (pwfx->wBitsPerSample == 16) { if ((err = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S16_LE)) < 0) { error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err)); return False; } } else { if ((err = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S8)) < 0) { error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err)); return False; } } #if 0 if ((err = snd_pcm_hw_params_set_rate_resample(pcm, hwparams, 1)) < 0) { error("snd_pcm_hw_params_set_rate_resample: %s\n", snd_strerror(err)); return False; } #endif rate = pwfx->nSamplesPerSec; if ((err = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, 0)) < 0) { error("snd_pcm_hw_params_set_rate_near: %s\n", snd_strerror(err)); return False; } audiochannels = pwfx->nChannels; if ((err = snd_pcm_hw_params_set_channels(pcm, hwparams, pwfx->nChannels)) < 0) { error("snd_pcm_hw_params_set_channels: %s\n", snd_strerror(err)); return False; } buffertime = 500000; /* microseconds */ if ((err = snd_pcm_hw_params_set_buffer_time_near(pcm, hwparams, &buffertime, 0)) < 0) { error("snd_pcm_hw_params_set_buffer_time_near: %s\n", snd_strerror(err)); return False; } if ((err = snd_pcm_hw_params(pcm, hwparams)) < 0) { error("snd_pcm_hw_params: %s\n", snd_strerror(err)); return False; } snd_pcm_hw_params_free(hwparams); if ((err = snd_pcm_prepare(pcm)) < 0) { error("snd_pcm_prepare: %s\n", snd_strerror(err)); return False; } reopened = True; return True; }
int main() { int fp; unsigned int pcm, tmp, dir; int buff_size; long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; snd_pcm_uframes_t frames; char *buff; int rate, channels, seconds; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr,"unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_U8); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 1); /* 44100 bits/second sampling rate (CD quality) */ val = 8000; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle,params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr,"unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buff large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buff = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 50000000 / val; fp=open("222.wav",O_WRONLY); while (loops > 0) { loops--; bzero(buff,sizeof(buff)); rc = snd_pcm_readi(handle, buff, frames); write(fp,buff,128); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr,"error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } /*rc = write(1, buff, size); if (rc != size) fprintf(stderr,"short write: wrote %d bytes\n", rc); */ } snd_pcm_drain(handle); snd_pcm_close(handle); free(buff); return 0; }
// alsa main (int argc, char *argv[]) { int i; int err; short buf[128]; snd_pcm_t *playback_handle; snd_pcm_hw_params_t *hw_params; if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", argv[1], snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, 44100, 0)) < 0) { fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) { fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); exit (1); } snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_prepare (playback_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } for (i = 0; i < 10; ++i) { if ((err = snd_pcm_writei (playback_handle, buf, 128)) != 128) { fprintf (stderr, "write to audio interface failed (%s)\n", snd_strerror (err)); exit (1); } } snd_pcm_close (playback_handle); exit (0); }
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; }
main() { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; unsigned char *buffer; int i=0; /* socket setting */ int sd; struct sockaddr_in s_addr; int n, n_send, status; int on = 1; sd = socket (AF_INET, SOCK_DGRAM, 0); bzero(&s_addr, sizeof(s_addr)); s_addr.sin_family = AF_INET; s_addr.sin_addr.s_addr = inet_addr("192.168.42.255"); s_addr.sin_port = htons(2007); if((status = setsockopt(sd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))) != 0 ) { printf("setsockopt error\n"); exit(-1); } /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "plughw:1,0", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_U8); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 1); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames =4800; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames *1; /* 2 bytes/sample, 2 channels */ buffer = (unsigned char*) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); while (1) { rc = snd_pcm_readi(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } if ((n_send = sendto(sd, buffer, strlen(buffer), 0, (struct sockaddr *)&s_addr, sizeof(s_addr))) < 0 ) { fprintf(stderr, "sendto() error"); exit(-3); } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); close(sd); }
bool QAudioInputPrivate::open() { #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; #endif clockStamp.restart(); timeStamp.restart(); elapsedTimeOffset = 0; int dir; int err = 0; int count=0; unsigned int freakuency=settings.frequency(); if (!settings.isValid()) { qWarning("QAudioOutput: open error, invalid format."); } else if (settings.sampleRate() <= 0) { qWarning("QAudioOutput: open error, invalid sample rate (%d).", settings.sampleRate()); } else { err = -1; } if (err == 0) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; emit errorChanged(errorState); return false; } QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioInput); if(dev.compare(QLatin1String("default")) == 0) { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) if (devices.size() > 0) dev = QLatin1String(devices.first()); else return false; #else dev = QLatin1String("hw:0,0"); #endif } else { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(m_device); #else int idx = 0; char *name; QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData()); while(snd_card_get_name(idx,&name) == 0) { if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0) break; idx++; } dev = QString(QLatin1String("hw:%1,0")).arg(idx); #endif } // Step 1: try and open the device while((count < 5) && (err < 0)) { err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0); if(err < 0) count++; } if (( err < 0)||(handle == 0)) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); return false; } snd_pcm_nonblock( handle, 0 ); // Step 2: Set the desired HW parameters. snd_pcm_hw_params_alloca( &hwparams ); bool fatal = false; QString errMessage; unsigned int chunks = 8; err = snd_pcm_hw_params_any( handle, hwparams ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_any: err = %1").arg(err); } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_access( handle, hwparams, access ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_access: err = %1").arg(err); } } if ( !fatal ) { err = setFormat(); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_format: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_channels: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params: err = %1").arg(err); } } if( err < 0) { qWarning()<<errMessage; errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); return false; } snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames); buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames); snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir); period_size = snd_pcm_frames_to_bytes(handle,period_frames); snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir); snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); // Step 3: Set the desired SW parameters. snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(handle, swparams); snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames); snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames); snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames); snd_pcm_sw_params(handle, swparams); // Step 4: Prepare audio ringBuffer.resize(buffer_size); snd_pcm_prepare( handle ); snd_pcm_start(handle); // Step 5: Setup timer bytesAvailable = checkBytesReady(); if(pullMode) connect(audioSource,SIGNAL(readyRead()),this,SLOT(userFeed())); // Step 6: Start audio processing chunks = buffer_size/period_size; timer->start(period_time*chunks/2000); errorState = QAudio::NoError; totalTimeValue = 0; return true; }
void play(int sec, int freq, char *file) { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; int fd; /* Check ranges */ if (sec < 1 || sec > 4000) { printf("WARNING: Incorrect time to play range [1,4000] s\n"); printf("\tSetting time to play to 5s...\n"); sec = 5; } if (freq < 1000 || freq > 100000) { printf("ERROR: Incorrect frequency range [1000,100000] Hz\n"); printf("\tSetting frequency to 44.1 kHz...\n"); freq = 44100; } /* Open file */ fd = open(file, O_RDONLY); if (fd < 0) { /* There was an error opening the file */ printf("ERROR: Couldn't open file to play\n"); printf("\tPlease make sure file exists\n"); } else { /* Print that the file is playing with its parameters */ printf("Playing file %s for %d seconds", file, sec); printf(" and frequency %d...\n", freq); /* Open PCM device for playback */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values */ snd_pcm_hw_params_any(handle, params); /* Set hardware parameters */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* freq bits/second sampling rate (CD quality) */ val = freq; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); /* We want to loop for sec seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); /* sec seconds in microseconds divided by period time */ loops = sec*1000000 / val; while (loops > 0) { loops--; rc = read(fd, buffer, size); if (rc == 0) { fprintf(stderr, "end of file on input\n"); break; } else if (rc != size) { fprintf(stderr, "short read: read %d bytes\n", rc); } rc = snd_pcm_writei(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short write, write %d frames\n", rc); } } /*Close handle and free buffer*/ snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); } }
/*---------------------------------------------------------------------- | AlsaOutput_Write +---------------------------------------------------------------------*/ static BLT_Result AlsaOutput_Write(AlsaOutput* self, void* buffer, BLT_Size size) { int watchdog = 5; int io_result; unsigned int sample_count; unsigned int sample_size; BLT_Result result; /* ensure that the device is prepared */ result = AlsaOutput_Prepare(self); if (BLT_FAILED(result)) return result; /* compute the number of samples */ sample_size = self->media_type.channel_count*self->media_type.bits_per_sample/8; sample_count = size / sample_size; /* write samples to the device and handle underruns */ do { while (sample_count) { io_result = snd_pcm_writei(self->device_handle, buffer, sample_count); if (io_result > 0) { buffer = (void*)((char*)buffer + io_result*sample_size); if ((unsigned int)io_result <= sample_count) { sample_count -= io_result; } else { /* strange, snd_pcm_writei returned more than we wrote */ sample_count = 0; } } else { break; } } if (sample_count == 0) return BLT_SUCCESS; /* we reach this point if the first write failed */ if (io_result < 0) { snd_pcm_status_t* status; snd_pcm_state_t state; snd_pcm_status_alloca_no_assert(&status); io_result = snd_pcm_status(self->device_handle, status); if (io_result != 0) { return BLT_FAILURE; } state = snd_pcm_status_get_state(status); if (state == SND_PCM_STATE_XRUN) { ATX_LOG_FINE("**** UNDERRUN *****"); /* re-prepare the channel */ io_result = snd_pcm_prepare(self->device_handle); if (io_result != 0) { return BLT_FAILURE; } } else { ATX_LOG_WARNING_1("**** STATE = %d ****", state); } } else { ATX_LOG_WARNING_1("snd_pcm_writei() returned %d", io_result); } ATX_LOG_FINE("**** RETRY *****"); } while(watchdog--); ATX_LOG_SEVERE("**** THE WATCHDOG BIT US ****"); return BLT_FAILURE; }
void *audiothread(void *v) { int policy; sched_param sched; int err; alsaaudio *dev; pthread_getschedparam(pthread_self(),&policy,&sched); sched.sched_priority++;//policy=SCHED_RR; pthread_setschedparam(pthread_self(),policy,&sched); dev=(alsaaudio*)v; unsigned int val; snd_pcm_t *fd; snd_pcm_uframes_t periodsize; snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_alloca(&hwparams); int output_rate; int channels; int fragment_size; int fragment_count; err=snd_pcm_open(&fd, strdup("default"), SND_PCM_STREAM_PLAYBACK, 0); if (err<0) return -1; fragment_size=LINUXFRAG; //overall buffer size fragment_count=2; //2 - 16 fragment count - 2 minimum, the lower it is potentially the lower the latency //configure device if (snd_pcm_hw_params_any(fd, hwparams) < 0) { //printf("linuxaudio failed at params any\n"); return -1; } if (snd_pcm_hw_params_set_access(fd, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { //printf("linuxaudio failed at set access\n"); return -1; } if (snd_pcm_hw_params_set_format(fd, hwparams,SND_PCM_FORMAT_S16_LE) < 0) { //printf("linuxaudio failed at set format\n"); return -1; } val = 44100; if (snd_pcm_hw_params_set_rate_near(fd, hwparams,&val, 0) < 0) { // Try 48KHZ too //printf("linuxaudio - %d HZ not available, trying 48000HZ\n", output_rate); val = 48000; if (snd_pcm_hw_params_set_rate_near(fd, hwparams,&val, 0) < 0) { //printf("linuxaudio failed at setting output rate (%d)\n", output_rate); return -1; } dev->mix->freq=val; } channels=2; if (snd_pcm_hw_params_set_channels(fd, hwparams, channels) < 0) { //printf("linuxaudio failed at set channels (%d)\n", channels); return -1; } periodsize = (fragment_size) / 4; // bytes -> frames for 16-bit,stereo - should be a minimum of 512 if (snd_pcm_hw_params_set_period_size_near(fd, hwparams,&periodsize, 0) < 0) { //printf("linuxaudio failed at set period size (%d)\n", (int)periodsize); return -1; } val = fragment_count; if (snd_pcm_hw_params_set_periods_near(fd, hwparams,&val, 0) < 0) { //printf("linuxaudio failed at set periods (%d)\n", val); //should attempt a one by one period increase up to 16? return -1; } if (snd_pcm_hw_params(fd, hwparams) < 0) { //printf("linuxaudio failed at installing hw params\n"); return -1; } //loop while playing sound dev->playing=1; while (dev->playing) { dev->mix->mix16(dev->buffer); if ((snd_pcm_writei (fd, dev->buffer,LINUXFRAG/2)) < 0) { //Half buffer for two channels? //printf ("linuxaudio warning: buffer underrun occurred\n"); if (snd_pcm_prepare(fd) < 0) { //printf ("linuxaudio failed at preparing pcm\n"); dev->playing=0; //die gracefully } } } snd_pcm_drop(fd); snd_pcm_close (fd); return 0; }
static int alsa_open (struct sound_params *sound_params) { snd_pcm_hw_params_t *hw_params; int err; unsigned int period_time; unsigned int buffer_time; snd_pcm_uframes_t chunk_frames; snd_pcm_uframes_t buffer_frames; char fmt_name[128]; switch (sound_params->fmt & SFMT_MASK_FORMAT) { case SFMT_S8: params.format = SND_PCM_FORMAT_S8; break; case SFMT_U8: params.format = SND_PCM_FORMAT_U8; break; case SFMT_S16: params.format = SND_PCM_FORMAT_S16; break; case SFMT_U16: params.format = SND_PCM_FORMAT_U16; break; case SFMT_S32: params.format = SND_PCM_FORMAT_S32; break; case SFMT_U32: params.format = SND_PCM_FORMAT_U32; break; default: error ("Unknown sample format: %s", sfmt_str(sound_params->fmt, fmt_name, sizeof(fmt_name))); params.format = SND_PCM_FORMAT_UNKNOWN; return 0; } if ((err = snd_pcm_open(&handle, options_get_str("AlsaDevice"), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { error ("Can't open audio: %s", snd_strerror(err)); return 0; } if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { error ("Can't allocate alsa hardware parameters structure: %s", snd_strerror(err)); return 0; } if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) { error ("Can't initialize hardware parameters structure: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { error ("Can't set alsa access type: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_set_format (handle, hw_params, params.format)) < 0) { error ("Can't set sample format: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } params.rate = sound_params->rate; if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, ¶ms.rate, 0)) < 0) { error ("Can't set sample rate: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } logit ("Set rate to %d", params.rate); if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, sound_params->channels)) < 0) { error ("Can't set number of channels: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &buffer_time, 0)) < 0) { error ("Can't get maximum buffer time: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if (buffer_time > BUFFER_MAX_USEC) buffer_time = BUFFER_MAX_USEC; period_time = buffer_time / 4; if ((err = snd_pcm_hw_params_set_period_time_near(handle, hw_params, &period_time, 0)) < 0) { error ("Can't set period time: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params_set_buffer_time_near(handle, hw_params, &buffer_time, 0)) < 0) { error ("Can't set buffer time: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) { error ("Can't set audio parameters: %s", snd_strerror(err)); snd_pcm_hw_params_free (hw_params); return 0; } snd_pcm_hw_params_get_period_size (hw_params, &chunk_frames, 0); snd_pcm_hw_params_get_buffer_size (hw_params, &buffer_frames); bytes_per_frame = sound_params->channels * sfmt_Bps(sound_params->fmt); logit ("Buffer time: %ldus", buffer_frames * bytes_per_frame); if (chunk_frames == buffer_frames) { error ("Can't use period equal to buffer size (%lu == %lu)", chunk_frames, buffer_frames); snd_pcm_hw_params_free (hw_params); return 0; } chunk_size = chunk_frames * bytes_per_frame; debug ("Chunk size: %d", chunk_size); snd_pcm_hw_params_free (hw_params); if ((err = snd_pcm_prepare(handle)) < 0) { error ("Can't prepare audio interface for use: %s", snd_strerror(err)); return 0; } debug ("ALSA device initialized"); params.channels = sound_params->channels; alsa_buf_fill = 0; return 1; }
static int ca_thread_func (void *arg) { struct alsa_stream* stream = (struct alsa_stream*) arg; snd_pcm_t* pcm = stream->ca_pcm; int size = stream->ca_buf_size; snd_pcm_uframes_t nframes = stream->ca_frames; void* user_data = stream->user_data; char* buf = stream->ca_buf; pj_timestamp tstamp; int result; struct sched_param param; pthread_t* thid; thid = (pthread_t*) pj_thread_get_os_handle (pj_thread_this()); param.sched_priority = sched_get_priority_max (SCHED_RR); PJ_LOG (5,(THIS_FILE, "ca_thread_func(%u): Set thread priority " "for audio capture thread.", (unsigned)syscall(SYS_gettid))); result = pthread_setschedparam (*thid, SCHED_RR, ¶m); if (result) { if (result == EPERM) PJ_LOG (5,(THIS_FILE, "Unable to increase thread priority, " "root access needed.")); else PJ_LOG (5,(THIS_FILE, "Unable to increase thread priority, " "error: %d", result)); } pj_bzero (buf, size); tstamp.u64 = 0; TRACE_((THIS_FILE, "ca_thread_func(%u): Started", (unsigned)syscall(SYS_gettid))); snd_pcm_prepare (pcm); while (!stream->quit) { pjmedia_frame frame; pj_bzero (buf, size); result = snd_pcm_readi (pcm, buf, nframes); if (result == -EPIPE) { PJ_LOG (4,(THIS_FILE, "ca_thread_func: overrun!")); snd_pcm_prepare (pcm); continue; } else if (result < 0) { PJ_LOG (4,(THIS_FILE, "ca_thread_func: error reading data!")); } if (stream->quit) break; frame.type = PJMEDIA_FRAME_TYPE_AUDIO; frame.buf = (void*) buf; frame.size = size; frame.timestamp.u64 = tstamp.u64; frame.bit_info = 0; result = stream->ca_cb (user_data, &frame); if (result != PJ_SUCCESS || stream->quit) break; tstamp.u64 += nframes; } snd_pcm_drain (pcm); TRACE_((THIS_FILE, "ca_thread_func: Stopped")); return PJ_SUCCESS; }
int main(int argc, char **argv){ int i; int aver,val,val2; int16_t buf[BUFSIZE]; double d_buffer[BUFSIZE]; double pitch = 0.0; struct timespec before,after; struct pitch_tracker_params *settings; snd_pcm_uframes_t period_size = PERIOD_SIZE; //ALSA PCM configuration snd_pcm_t *handle; snd_pcm_hw_params_t *params; int dir,rc; snd_pcm_uframes_t frames; /* Open PCM device for capture */ rc = snd_pcm_open( &handle, "default" , SND_PCM_STREAM_CAPTURE , 0); if(rc < 0 ){ fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED); /* unsigned 16-bit format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16); snd_pcm_hw_params_set_channels(handle, params, 1); /* 44100 bits/second sampling rate */ val = 44100; snd_pcm_hw_params_set_rate_near(handle,params, &val, &dir); /* set size time*/ snd_pcm_hw_params_set_period_size_near(handle, params, &period_size , &dir); /* write configuration */ rc = snd_pcm_hw_params(handle,params); /*Display info*/ printf("PCM handle 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_access(params, (snd_pcm_access_t *) &val); printf("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val)); snd_pcm_hw_params_get_format(params, &val); printf("format = '%s' (%s)\n", snd_pcm_format_name((snd_pcm_format_t)val), snd_pcm_format_description( (snd_pcm_format_t)val)); snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t *)&val); printf("subformat = '%s' (%s)\n", snd_pcm_subformat_name((snd_pcm_subformat_t)val), snd_pcm_subformat_description( (snd_pcm_subformat_t)val)); snd_pcm_hw_params_get_channels(params, &val); printf("channels = %d\n", val); snd_pcm_hw_params_get_rate(params, &val, &dir); printf("rate = %d bps\n", val); snd_pcm_hw_params_get_period_time(params, &val, &dir); printf("period time = %d us\n", val); snd_pcm_hw_params_get_period_size(params, &frames, &dir); printf("period size = %d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_time(params, &val, &dir); printf("buffer time = %d us\n", val); snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val); printf("buffer size = %d frames\n", val); snd_pcm_hw_params_get_periods(params, &val, &dir); printf("periods per buffer = %d frames\n", val); snd_pcm_hw_params_get_rate_numden(params, &val, &val2); printf("exact rate = %d/%d bps\n", val, val2); val = snd_pcm_hw_params_get_sbits(params); printf("significant bits = %d\n", val); val = snd_pcm_hw_params_is_batch(params); printf("is batch = %d\n", val); val = snd_pcm_hw_params_is_block_transfer(params); printf("is block transfer = %d\n", val); val = snd_pcm_hw_params_is_double(params); printf("is double = %d\n", val); val = snd_pcm_hw_params_is_half_duplex(params); printf("is half duplex = %d\n", val); val = snd_pcm_hw_params_is_joint_duplex(params); printf("is joint duplex = %d\n", val); val = snd_pcm_hw_params_can_overrange(params); printf("can overrange = %d\n", val); val = snd_pcm_hw_params_can_mmap_sample_resolution(params); printf("can mmap = %d\n", val); val = snd_pcm_hw_params_can_pause(params); printf("can pause = %d\n", val); val = snd_pcm_hw_params_can_resume(params); printf("can resume = %d\n", val); val = snd_pcm_hw_params_can_sync_start(params); printf("can sync start = %d\n", val); settings = open_pitch_tracker(); while(1){ rc = snd_pcm_readi(handle, buf, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } for( i = 0 ; i< BUFSIZE ; i++){ d_buffer[i] = (double) buf[i]; } pitch = compute_pitch(d_buffer, BUFSIZE, S16, settings ,ACCURACY); if( pitch != 0.0 ) printf("frequency -> %f\n",pitch); memset(buf,0,BUFSIZE); } close_pitch_tracker(&settings); snd_pcm_drain(handle); snd_pcm_close(handle); return 0; }
void WaveRecorder::stop() { snd_pcm_drop(_pcm); snd_pcm_prepare(_pcm); }
bool CAESinkALSA::Initialize(AEAudioFormat &format, std::string &device) { m_initDevice = device; m_initFormat = format; /* if we are raw, correct the data format */ if (AE_IS_RAW(format.m_dataFormat)) { m_channelLayout = GetChannelLayout(format); format.m_dataFormat = AE_FMT_S16NE; m_passthrough = true; } else { m_channelLayout = GetChannelLayout(format); m_passthrough = false; } #if defined(HAS_AMLPLAYER) || defined(HAS_LIBAMCODEC) if (aml_present()) { aml_set_audio_passthrough(m_passthrough); device = "default"; } #endif if (m_channelLayout.Count() == 0) { CLog::Log(LOGERROR, "CAESinkALSA::Initialize - Unable to open the requested channel layout"); return false; } format.m_channelLayout = m_channelLayout; AEDeviceType devType = AEDeviceTypeFromName(device); std::string AESParams; /* digital interfaces should have AESx set, though in practice most * receivers don't care */ if (m_passthrough || devType == AE_DEVTYPE_HDMI || devType == AE_DEVTYPE_IEC958) GetAESParams(format, AESParams); CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Attempting to open device \"%s\"", device.c_str()); /* get the sound config */ snd_config_t *config; snd_config_copy(&config, snd_config); if (!OpenPCMDevice(device, AESParams, m_channelLayout.Count(), &m_pcm, config)) { CLog::Log(LOGERROR, "CAESinkALSA::Initialize - failed to initialize device \"%s\"", device.c_str()); snd_config_delete(config); return false; } /* get the actual device name that was used */ device = snd_pcm_name(m_pcm); m_device = device; CLog::Log(LOGINFO, "CAESinkALSA::Initialize - Opened device \"%s\"", device.c_str()); /* free the sound config */ snd_config_delete(config); if (!InitializeHW(format) || !InitializeSW(format)) return false; snd_pcm_nonblock(m_pcm, 1); snd_pcm_prepare (m_pcm); m_format = format; m_formatSampleRateMul = 1.0 / (double)m_format.m_sampleRate; return true; }
int main() { const snd_pcm_channel_area_t *areas; int size; unsigned char *buffer; char *pcm_name; unsigned int rate = 8000; int chan; int rc; unsigned int val; char check; int pcmreturn; //Set PCM stream and handle snd_pcm_t *pcm_handle; snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; //Set HARDWARE parameters snd_pcm_hw_params_t *hwparams; //pcm_name = (char *)malloc(10); pcm_name = "plughw:0,0"; //allocate memory for hardware if(snd_pcm_hw_params_malloc(&hwparams)<0) { fprintf(stderr,"No memory allocated for hardware"); return(-1); } if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", pcm_name); return(-1); } //INITIALIZE HARDWARE WITH CONFIGURATION OF THE SOUNDCARD if(snd_pcm_hw_params_any(pcm_handle,hwparams)<0) { fprintf(stderr,"The hardware device cannot be configured\n"); } //SET FORMAT TO 16 BIT LITTLE ENDIAN snd_pcm_hw_params_set_format(pcm_handle,hwparams,SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(pcm_handle,hwparams,2); /* 44100 bits/second sampling rate (CD quality) */ if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); return(-1); } //SETTING RATE ie SAMPLING FREQUENCY snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0); //SETTING HARDWARE PARAMETERS if(rc=(snd_pcm_hw_params(pcm_handle,hwparams))<0) { fprintf(stderr,"\nCannot set hardware parameters\n"); return -1; } //snd_pcm_uframes_t periodsize = 8192; snd_pcm_uframes_t frames,offset ;//OF TYPE UNSIGNED LONG snd_pcm_sframes_t commitres; //frames =32; //SETTING SOME MORE PARAMETERS //size = frames*4; //SETTING BUFFER SIZE /*if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize*2)>>2) < 0) { fprintf(stderr, "Error setting buffersize.\n"); return(-1); } */ int first=0;; int err; snd_pcm_sframes_t avail = snd_pcm_avail_update(pcm_handle); printf("\nNumber of frames available is : %d \n",(int)avail); //------------------------------------------------------------------------------------------------------- //<<<<<<<<<<<<<<<<<<<<<<DISPLAYING INFORMATION>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //Buffer size snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*)&val); printf("\nThe buffer size is %d \n",val); //Buffer time snd_pcm_hw_params_get_buffer_time(hwparams, &val,0); printf("\nBuffer time is : %d \n",val); //Period size snd_pcm_hw_params_get_period_size(hwparams,&frames,0); printf("\nperiod size : %d \n",(int)frames); //////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// //<<<<<<<<<<<<<mmap_begin>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> err=snd_pcm_mmap_begin(pcm_handle,&areas,&offset,&frames); //Periods between buffer snd_pcm_hw_params_get_periods(hwparams,&val,0); printf("\n Periods between buffer is : %d \n",val); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>. if(err<0) { printf("\nMMAP error\n"); return -1; } else printf("\n%d\n",err); /* commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames); if(commitres<0) { printf("\nFrames not committed to memory\n"); } */ //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,OPENING FILE>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.... int dest = open("sample3.wav",O_RDONLY); if(dest<0) { perror("\nFile could not be opened\n"); return -1; } //buffer = (unsigned char *)malloc(1000); /* unsigned long buf = offset; if(read(dest,&offset,1)<0) { perror("\nNo destination for read\n"); return -1; } */ /* avail=snd_pcm_avail_update(pcm_handle); printf("\nAvailable frames = %d \n\n",(int)avail); struct timeval tvbefore,tvafter; gettimeofday(&tvbefore,NULL); */ unsigned char *ptr[2]; int i; //unsigned int steps=0; for(i=0;i<2;i++) ptr[i] = (unsigned char*)areas[i].addr + (areas[i].first/8) + offset*(areas[i].step/8); printf("\nOffset of the first sample : %u \n",areas[0].first); printf("\n\nOffset of the memory map is : %u \n",areas[0].step/8); printf("\nAreas start address is : %u \n",areas[0].addr); printf("\nNumber of frames ; %u \n",frames); printf("\n\nPointer before ; %u \n",ptr[0]); long pl; for(pl=0;pl<100000;pl++); if(ptr[1]==NULL) printf("\nNull pointer 1 allocated\n"); if(ptr[0]==NULL) printf("\nNull pointer 0 allocated \n"); int check2=1; snd_pcm_sframes_t size2 =30; while(1) { for(i=0;i<2;i++) { //ptr[i] = (unsigned char*)areas[i].addr + (areas[i].first/8) + offset*(areas[i].step/8); if(read(dest,ptr[i],120)!=0) { if(ptr[i]!=NULL) { if(pcmreturn = snd_pcm_mmap_writei(pcm_handle,ptr[i],size2)<0) { snd_pcm_prepare(pcm_handle); printf("\n<<<<<<<Buffer Underrun>>>>>>>>\n"); break; } // printf("\n%d\n",pcmreturn); ptr[i]+=0; printf("\n%lu\n",ptr[i]); } } else { check2=0; break; } } if(check2==0) break; // l:break; } commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames); if(commitres<0) { printf("\nFrames not committed to memory\n"); } }
static HRESULT SetFormat(IDsDriverBufferImpl *This, LPWAVEFORMATEX pwfx) { snd_pcm_t *pcm = NULL; snd_pcm_hw_params_t *hw_params = This->hw_params; unsigned int buffer_time = 500000; snd_pcm_format_t format = -1; snd_pcm_uframes_t psize; DWORD rate = pwfx->nSamplesPerSec; int err=0; switch (pwfx->wBitsPerSample) { case 8: format = SND_PCM_FORMAT_U8; break; case 16: format = SND_PCM_FORMAT_S16_LE; break; case 24: format = SND_PCM_FORMAT_S24_3LE; break; case 32: format = SND_PCM_FORMAT_S32_LE; break; default: FIXME("Unsupported bpp: %d\n", pwfx->wBitsPerSample); return DSERR_GENERIC; } err = snd_pcm_open(&pcm, WOutDev[This->drv->wDevID].pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (err < 0) { if (errno != EBUSY || !This->pcm) { WARN("Cannot open sound device: %s\n", snd_strerror(err)); return DSERR_GENERIC; } snd_pcm_drop(This->pcm); snd_pcm_close(This->pcm); This->pcm = NULL; err = snd_pcm_open(&pcm, WOutDev[This->drv->wDevID].pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (err < 0) { WARN("Cannot open sound device: %s\n", snd_strerror(err)); return DSERR_BUFFERLOST; } } /* Set some defaults */ snd_pcm_hw_params_any(pcm, hw_params); err = snd_pcm_hw_params_set_channels(pcm, hw_params, pwfx->nChannels); if (err < 0) { WARN("Could not set channels to %d\n", pwfx->nChannels); goto err; } err = snd_pcm_hw_params_set_format(pcm, hw_params, format); if (err < 0) { WARN("Could not set format to %d bpp\n", pwfx->wBitsPerSample); goto err; } /* Alsa's rate resampling is only used if the application specifically requests * a buffer at a certain frequency, else it is better to disable it due to unwanted * side effects, which may include: Less granular pointer, changing buffer sizes, etc */ #if SND_LIB_VERSION >= 0x010009 snd_pcm_hw_params_set_rate_resample(pcm, hw_params, 0); #endif err = snd_pcm_hw_params_set_rate_near(pcm, hw_params, &rate, NULL); if (err < 0) { rate = pwfx->nSamplesPerSec; WARN("Could not set rate\n"); goto err; } if (!ALSA_NearMatch(rate, pwfx->nSamplesPerSec)) { WARN("Could not set sound rate to %d, but instead to %d\n", pwfx->nSamplesPerSec, rate); pwfx->nSamplesPerSec = rate; pwfx->nAvgBytesPerSec = rate * pwfx->nBlockAlign; /* Let DirectSound detect this */ } snd_pcm_hw_params_set_periods_integer(pcm, hw_params); snd_pcm_hw_params_set_buffer_time_near(pcm, hw_params, &buffer_time, NULL); buffer_time = 10000; snd_pcm_hw_params_set_period_time_near(pcm, hw_params, &buffer_time, NULL); err = snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL); buffer_time = 16; snd_pcm_hw_params_set_periods_near(pcm, hw_params, &buffer_time, NULL); if (!This->mmap) { HeapFree(GetProcessHeap(), 0, This->mmap_buffer); This->mmap_buffer = NULL; } err = snd_pcm_hw_params_set_access (pcm, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (err >= 0) This->mmap = 1; else { This->mmap = 0; err = snd_pcm_hw_params_set_access (pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); } err = snd_pcm_hw_params(pcm, hw_params); /* ALSA needs at least 3 buffers to work successfully */ This->mmap_commitahead = 3 * psize; while (This->mmap_commitahead <= 512) This->mmap_commitahead += psize; if (This->pcm) { snd_pcm_drop(This->pcm); snd_pcm_close(This->pcm); } This->pcm = pcm; snd_pcm_prepare(This->pcm); DSDB_CreateMMAP(This); return S_OK; err: if (err < 0) WARN("Failed to apply changes: %s\n", snd_strerror(err)); if (!This->pcm) This->pcm = pcm; else snd_pcm_close(pcm); if (This->pcm) snd_pcm_hw_params_current(This->pcm, This->hw_params); return DSERR_BADFORMAT; }
static void rdpsnd_alsa_set_params(rdpsndAlsaPlugin* alsa) { snd_pcm_hw_params_t* hw_params; snd_pcm_sw_params_t* sw_params; int error; snd_pcm_uframes_t frames; snd_pcm_uframes_t start_threshold; snd_pcm_drop(alsa->out_handle); error = snd_pcm_hw_params_malloc(&hw_params); if (error < 0) { DEBUG_WARN("snd_pcm_hw_params_malloc failed"); return; } snd_pcm_hw_params_any(alsa->out_handle, hw_params); snd_pcm_hw_params_set_access(alsa->out_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(alsa->out_handle, hw_params, alsa->format); snd_pcm_hw_params_set_rate_near(alsa->out_handle, hw_params, &alsa->actual_rate, NULL); snd_pcm_hw_params_set_channels_near(alsa->out_handle, hw_params, &alsa->actual_channels); if (alsa->latency < 0) frames = alsa->actual_rate * 4; /* Default to 4-second buffer */ else frames = alsa->latency * alsa->actual_rate * 2 / 1000; /* Double of the latency */ if (frames < alsa->actual_rate / 2) frames = alsa->actual_rate / 2; /* Minimum 0.5-second buffer */ snd_pcm_hw_params_set_buffer_size_near(alsa->out_handle, hw_params, &frames); snd_pcm_hw_params(alsa->out_handle, hw_params); snd_pcm_hw_params_free(hw_params); error = snd_pcm_sw_params_malloc(&sw_params); if (error < 0) { DEBUG_WARN("snd_pcm_sw_params_malloc failed"); return; } snd_pcm_sw_params_current(alsa->out_handle, sw_params); if (alsa->latency == 0) start_threshold = 0; else start_threshold = frames / 2; snd_pcm_sw_params_set_start_threshold(alsa->out_handle, sw_params, start_threshold); snd_pcm_sw_params(alsa->out_handle, sw_params); snd_pcm_sw_params_free(sw_params); snd_pcm_prepare(alsa->out_handle); DEBUG_SVC("hardware buffer %d frames, playback buffer %.2g seconds", (int)frames, (double)frames / 2.0 / (double)alsa->actual_rate); if ((alsa->actual_rate != alsa->source_rate) || (alsa->actual_channels != alsa->source_channels)) { DEBUG_SVC("actual rate %d / channel %d is different from source rate %d / channel %d, resampling required.", alsa->actual_rate, alsa->actual_channels, alsa->source_rate, alsa->source_channels); } }
alsa_dev_t* alsa_open(char *name) { alsa_dev_t *alsa_dev = NULL; snd_pcm_hw_params_t *params = NULL; uint32_t val = 0; int32_t rc = 0; int32_t dir = 0; alsa_dev = malloc(sizeof(alsa_dev_t)); if (!alsa_dev) { syslog(LOG_ERR, "Failed to create audio device: Out of memory"); exit(EXIT_FAILURE); } /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&alsa_dev->snd_pcm, name, SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { syslog(LOG_ERR, "Cannot open pcm device: %s", snd_strerror(rc)); exit(EXIT_FAILURE); } alsa_dev->name = name; /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(alsa_dev->snd_pcm, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(alsa_dev->snd_pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(alsa_dev->snd_pcm, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(alsa_dev->snd_pcm, params, AUDIO_CHANNEL_NUM); /* 44100 bits/second sampling rate (CD quality) */ val = AUDIO_SAMPLE_RATE; snd_pcm_hw_params_set_rate_near(alsa_dev->snd_pcm, params, &val, &dir); alsa_dev->frames = 1152; snd_pcm_hw_params_set_period_size_near(alsa_dev->snd_pcm, params, &alsa_dev->frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(alsa_dev->snd_pcm, params); if (rc < 0) { syslog(LOG_ERR, "Cannot set hw parameters: %s", snd_strerror(rc)); exit(EXIT_FAILURE); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &alsa_dev->frames, &dir); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); snd_pcm_prepare(alsa_dev->snd_pcm); snd_pcm_start(alsa_dev->snd_pcm); return alsa_dev; }
static void alsa_configure (struct sound_device *sd) { int val, err, dir; unsigned uval; struct alsa_params *p = (struct alsa_params *) sd->data; snd_pcm_uframes_t buffer_size; xassert (p->handle != 0); err = snd_pcm_hw_params_malloc (&p->hwparams); if (err < 0) alsa_sound_perror ("Could not allocate hardware parameter structure", err); err = snd_pcm_sw_params_malloc (&p->swparams); if (err < 0) alsa_sound_perror ("Could not allocate software parameter structure", err); err = snd_pcm_hw_params_any (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not initialize hardware parameter structure", err); err = snd_pcm_hw_params_set_access (p->handle, p->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) alsa_sound_perror ("Could not set access type", err); val = sd->format; err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set sound format", err); uval = sd->sample_rate; err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0); if (err < 0) alsa_sound_perror ("Could not set sample rate", err); val = sd->channels; err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set channel count", err); err = snd_pcm_hw_params (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not set parameters", err); err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir); if (err < 0) alsa_sound_perror ("Unable to get period size for playback", err); err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size); if (err < 0) alsa_sound_perror ("Unable to get buffer size for playback", err); err = snd_pcm_sw_params_current (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to determine current swparams for playback", err); /* Start the transfer when the buffer is almost full */ err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams, (buffer_size / p->period_size) * p->period_size); if (err < 0) alsa_sound_perror ("Unable to set start threshold mode for playback", err); /* Allow the transfer when at least period_size samples can be processed */ err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size); if (err < 0) alsa_sound_perror ("Unable to set avail min for playback", err); err = snd_pcm_sw_params (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to set sw params for playback\n", err); snd_pcm_hw_params_free (p->hwparams); p->hwparams = NULL; snd_pcm_sw_params_free (p->swparams); p->swparams = NULL; err = snd_pcm_prepare (p->handle); if (err < 0) alsa_sound_perror ("Could not prepare audio interface for use", err); if (sd->volume > 0) { int chn; snd_mixer_t *handle; snd_mixer_elem_t *e; const char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE; if (snd_mixer_open (&handle, 0) >= 0) { if (snd_mixer_attach (handle, file) >= 0 && snd_mixer_load (handle) >= 0 && snd_mixer_selem_register (handle, NULL, NULL) >= 0) for (e = snd_mixer_first_elem (handle); e; e = snd_mixer_elem_next (e)) { if (snd_mixer_selem_has_playback_volume (e)) { long pmin, pmax, vol; snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax); vol = pmin + (sd->volume * (pmax - pmin)) / 100; for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) snd_mixer_selem_set_playback_volume (e, chn, vol); } } snd_mixer_close (handle); } } }
qint64 QAudioInputPrivate::read(char* data, qint64 len) { // Read in some audio data and write it to QIODevice, pull mode if ( !handle ) return 0; int bytesRead = 0; int bytesInRingbufferBeforeRead = ringBuffer.bytesOfDataInBuffer(); if (ringBuffer.bytesOfDataInBuffer() < len) { // bytesAvaiable is saved as a side effect of checkBytesReady(). int bytesToRead = checkBytesReady(); if (bytesToRead < 0) { // bytesAvailable as negative is error code, try to recover from it. xrun_recovery(bytesToRead); bytesToRead = checkBytesReady(); if (bytesToRead < 0) { // recovery failed must stop and set error. close(); errorState = QAudio::IOError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); return 0; } } bytesToRead = qMin<qint64>(len, bytesToRead); bytesToRead = qMin<qint64>(ringBuffer.freeBytes(), bytesToRead); bytesToRead -= bytesToRead % period_size; int count=0; int err = 0; while(count < 5 && bytesToRead > 0) { char buffer[bytesToRead]; int chunks = bytesToRead / period_size; int frames = chunks * period_frames; if (frames > (int)buffer_frames) frames = buffer_frames; int readFrames = snd_pcm_readi(handle, buffer, frames); if (readFrames >= 0) { bytesRead = snd_pcm_frames_to_bytes(handle, readFrames); ringBuffer.write(buffer, bytesRead); #ifdef DEBUG_AUDIO qDebug() << QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(bytesRead).arg(readFrames).toLatin1().constData(); #endif break; } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { errorState = QAudio::IOError; err = 0; break; } else { if(readFrames == -EPIPE) { errorState = QAudio::UnderrunError; err = snd_pcm_prepare(handle); } else if(readFrames == -ESTRPIPE) { err = snd_pcm_prepare(handle); } if(err != 0) break; } count++; } } bytesRead += bytesInRingbufferBeforeRead; if (bytesRead > 0) { // got some send it onward #ifdef DEBUG_AUDIO qDebug() << "frames to write to QIODevice = " << snd_pcm_bytes_to_frames( handle, (int)bytesRead ) << " (" << bytesRead << ") bytes"; #endif if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return 0; if (pullMode) { qint64 l = 0; qint64 bytesWritten = 0; while (ringBuffer.bytesOfDataInBuffer() > 0) { l = audioSource->write(ringBuffer.availableData(), ringBuffer.availableDataBlockSize()); if (l > 0) { ringBuffer.readBytes(l); bytesWritten += l; } else { break; } } if (l < 0) { close(); errorState = QAudio::IOError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); } else if (l == 0 && bytesWritten == 0) { if (deviceState != QAudio::IdleState) { errorState = QAudio::NoError; deviceState = QAudio::IdleState; emit stateChanged(deviceState); } } else { bytesAvailable -= bytesWritten; totalTimeValue += bytesWritten; resuming = false; if (deviceState != QAudio::ActiveState) { errorState = QAudio::NoError; deviceState = QAudio::ActiveState; emit stateChanged(deviceState); } } return bytesWritten; } else { while (ringBuffer.bytesOfDataInBuffer() > 0) { int size = ringBuffer.availableDataBlockSize(); memcpy(data, ringBuffer.availableData(), size); data += size; ringBuffer.readBytes(size); } bytesAvailable -= bytesRead; totalTimeValue += bytesRead; resuming = false; if (deviceState != QAudio::ActiveState) { errorState = QAudio::NoError; deviceState = QAudio::ActiveState; emit stateChanged(deviceState); } return bytesRead; } } return 0; }
//******************************************************************************* //* audio_thread_fxn ** //******************************************************************************* //* Input Parameters: ** //* void *envByRef -- a pointer to an audio_thread_env structure ** //* as defined in audio_thread.h ** //* ** //* envByRef.quit -- when quit != 0, thread will cleanup and exit ** //* ** //* Return Value: ** //* void * -- AUDIO_THREAD_SUCCESS or AUDIO_THREAD_FAILURE as ** //* defined in audio_thread.h ** //******************************************************************************* void *audio_thread_fxn( void *envByRef ) { // Variables and definitions // ************************* // Thread parameters and return value audio_thread_env * envPtr = envByRef; // < see above > void * status = AUDIO_THREAD_SUCCESS; // < see above > // The levels of initialization for initMask #define INPUT_ALSA_INITIALIZED 0x1 #define INPUT_BUFFER_ALLOCATED 0x2 #define OUTPUT_ALSA_INITIALIZED 0x4 #define OUTPUT_BUFFER_ALLOCATED 0x8 unsigned int initMask = 0x0; // Used to only cleanup items that were init'd // Input and output driver variables //FILE * inputFile = NULL; // Input file pointer (i.e. handle) snd_pcm_t *pcm_output_handle; snd_pcm_t *pcm_capture_handle; // Handle for the PCM device snd_pcm_uframes_t exact_bufsize; // bufsize is in frames. Each frame is 4 bytes int blksize = BLOCKSIZE; // Raw input or output frame size in bytes char *outputBuffer = NULL; char *outputBuffer2 = NULL; // Output buffer for driver to read from char *playingBuffer = NULL; // Thread Create Phase -- secure and initialize resources // ****************************************************** // Setup audio input device // ************************ // Open an ALSA device channel for audio input exact_bufsize = blksize/BYTESPERFRAME; if( audio_io_setup( &pcm_capture_handle, SOUND_DEVICE, SAMPLE_RATE, SND_PCM_STREAM_CAPTURE, &exact_bufsize ) == AUDIO_FAILURE ) { ERR( "Audio_input_setup failed in audio_thread_fxn\n\n" ); status = AUDIO_THREAD_FAILURE; goto cleanup; } DBG( "exact_bufsize = %d\n", (int) exact_bufsize); // Record that input OSS device was opened in initialization bitmask initMask |= INPUT_ALSA_INITIALIZED; blksize = exact_bufsize*BYTESPERFRAME; // Initialize audio output device // ****************************** // Initialize the output ALSA device DBG( "pcm_output_handle before audio_output_setup = %d\n", (int) pcm_output_handle); exact_bufsize = blksize/BYTESPERFRAME; DBG( "Requesting bufsize = %d\n", (int) exact_bufsize); if( audio_io_setup( &pcm_output_handle, OUT_SOUND_DEVICE, SAMPLE_RATE, SND_PCM_STREAM_PLAYBACK, &exact_bufsize) == AUDIO_FAILURE ) { ERR( "audio_output_setup failed in audio_thread_fxn\n" ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } blksize = exact_bufsize; DBG( "pcm_output_handle after audio_output_setup = %d\n", (int) pcm_output_handle); DBG( "blksize = %d, exact_bufsize = %d\n", blksize, (int) exact_bufsize); // Record that input ALSA device was opened in initialization bitmask initMask |= OUTPUT_ALSA_INITIALIZED; // Create output buffer to write from into ALSA output device if( ( outputBuffer = malloc( blksize ) ) == NULL ) { ERR( "Failed to allocate memory for output block (%d)\n", blksize ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } // Create 5 seconds of output buffer to circularly update if( ( outputBuffer2 = malloc( 500*blksize ) ) == NULL ) { ERR( "Failed to allocate memory for output block (%d)\n", blksize ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } // This adds the two audio files together for play when enter is pressed if( ( playingBuffer = malloc( 500*blksize ) ) == NULL ) { ERR( "Failed to allocate memory for output block (%d)\n", blksize ); status = AUDIO_THREAD_FAILURE; goto cleanup ; } DBG( "Allocated output audio buffer of size %d to address %p\n", blksize, outputBuffer ); // Record that the output buffer was allocated in initialization bitmask initMask |= OUTPUT_BUFFER_ALLOCATED; // Thread Execute Phase -- perform I/O and processing // ************************************************** // Get things started by sending some silent buffers out. int i; memset(outputBuffer, 0, blksize); // Clear the buffer memset(outputBuffer2, 0, blksize); // Clear the buffer memset(playingBuffer, 0, blksize); // Clear the buffer for(i=0; i<4; i++) { snd_pcm_readi(pcm_capture_handle, outputBuffer, blksize/BYTESPERFRAME); if ((snd_pcm_writei(pcm_output_handle, outputBuffer, exact_bufsize)) < 0) { snd_pcm_prepare(pcm_output_handle); ERR( "<<<Pre Buffer Underrun >>> \n"); } } // // Processing loop // DBG( "Entering audio_thread_fxn processing loop\n" ); int count = 0; //count for the specific audio frame being played int count2 = 0; //count to 500 to keep track of circular loop int flag = 0; //goes high to indicate that 500 frames are captured and ready to be played back int playaudiocheck = 1; //goes high to indicate that 500 frames have been played and are ready for capture and play again while( !envPtr->quit ) { // Read capture buffer from ALSA input device if( snd_pcm_readi(pcm_capture_handle, outputBuffer, blksize/BYTESPERFRAME) < 0 ) { snd_pcm_prepare(pcm_capture_handle); } // Write output buffer into ALSA output device if(!audiocaller || !flag){ //If not playing last five seconds of audio or the buffer isn't filled to the 5 second capacity, then we want to continue to play audio regularly if (snd_pcm_writei(pcm_output_handle, outputBuffer, blksize/BYTESPERFRAME) < 0) { snd_pcm_prepare(pcm_output_handle); // Send out an extra blank buffer if there is an underrun and try again. memset(outputBuffer, 0, blksize); // Clear the buffer snd_pcm_writei(pcm_output_handle, outputBuffer, exact_bufsize); } } //Now we want to check to see if the buffer is full and the audio needs to be played back as well as if the audio has finished playing back if(audiocaller && (count2 == 499) && playaudiocheck){ // This will determine that we are playing audio from this point as well we will say not to come back into this loop until the audio has been played and set count2 back to 0 for playing from the beginning count2 = 0; flag = 1; playaudiocheck = 0; } //Now we will play audio only if the flag says that we have a full buffer if(audiocaller && flag){ //We have to add the signals from what sound is currently happening to the sounds that happened over the last 5 seconds together and then have them playback byter for byte for(i=0; i < blksize; i++){ playingBuffer[i] = outputBuffer2[(count2*blksize)+i] + outputBuffer[i]; } //When the audio has been formed it them plays back through the speakers with a snd_pcm_writei call for playingBuffer if (snd_pcm_writei(pcm_output_handle, playingBuffer, blksize/BYTESPERFRAME) < 0){ snd_pcm_prepare(pcm_output_handle); // Send out an extra blank buffer if there is an underrun and try again. memset(playingBuffer, 0, blksize); // Clear the buffer snd_pcm_writei(pcm_output_handle, playingBuffer, blksize/BYTESPERFRAME); } //We now need to detect whether or not the buffer has come to an end and if it has we need to let the program know that we don't want to continue playing both audios together as well as let the buffer know it can be recalled to play again if(count2 > 498){ audiocaller = 0; playaudiocheck = 1; flag = 0; } } //Copies the recorded audio into the new buffer at the specified index memcpy(outputBuffer2 + (count2*blksize), outputBuffer, blksize); count++; count2++; count2 = count2 % 500; //DBG("%d, ", count++); } DBG("\n"); DBG( "Exited audio_thread_fxn processing loop\n" ); // Thread Delete Phase -- free up resources allocated by this file // *************************************************************** cleanup: DBG( "Starting audio thread cleanup to return resources to system\n" ); // Close output ALSA device if( initMask & OUTPUT_ALSA_INITIALIZED ) if( audio_io_cleanup( pcm_output_handle ) != AUDIO_SUCCESS ) { ERR( "audio_output_cleanup() failed for file descriptor %d\n", (int)pcm_output_handle ); status = AUDIO_THREAD_FAILURE; } // Free allocated buffers // ********************** // Free output buffer if( initMask & OUTPUT_BUFFER_ALLOCATED ) { free( outputBuffer ); free( outputBuffer2 ); free( playingBuffer ); DBG( "Freed audio output buffer at location %p\n", outputBuffer ); } // Return from audio_thread_fxn function // ************************************* // Return the status at exit of the thread's execution DBG( "Audio thread cleanup complete. Exiting audio_thread_fxn\n" ); return status; }
bool QAudioOutputPrivate::open() { if(opened) return true; #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; #endif timeStamp.restart(); elapsedTimeOffset = 0; int dir; int err=-1; int count=0; unsigned int freakuency=settings.frequency(); QString dev = QString(QLatin1String(m_device.constData())); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput); if(dev.compare(QLatin1String("default")) == 0) { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(devices.first()); #else dev = QLatin1String("hw:0,0"); #endif } else { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(m_device); #else int idx = 0; char *name; QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData()); while(snd_card_get_name(idx,&name) == 0) { if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0) break; idx++; } dev = QString(QLatin1String("hw:%1,0")).arg(idx); #endif } // Step 1: try and open the device while((count < 5) && (err < 0)) { err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); if(err < 0) count++; } if (( err < 0)||(handle == 0)) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; return false; } snd_pcm_nonblock( handle, 0 ); // Step 2: Set the desired HW parameters. snd_pcm_hw_params_alloca( &hwparams ); bool fatal = false; QString errMessage; unsigned int chunks = 8; err = snd_pcm_hw_params_any( handle, hwparams ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_any: err = %1").arg(err); } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_access( handle, hwparams, access ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_access: err = %1").arg(err); } } if ( !fatal ) { err = setFormat(); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_format: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_channels: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err); } } if ( !fatal ) { unsigned int maxBufferTime = 0; unsigned int minBufferTime = 0; unsigned int maxPeriodTime = 0; unsigned int minPeriodTime = 0; err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &maxBufferTime, &dir); if ( err >= 0) err = snd_pcm_hw_params_get_buffer_time_min(hwparams, &minBufferTime, &dir); if ( err >= 0) err = snd_pcm_hw_params_get_period_time_max(hwparams, &maxPeriodTime, &dir); if ( err >= 0) err = snd_pcm_hw_params_get_period_time_min(hwparams, &minPeriodTime, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: buffer/period min and max: err = %1").arg(err); } else { if (maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time) { #ifdef DEBUG_AUDIO qDebug()<<"defaults out of range"; qDebug()<<"pmin="<<minPeriodTime<<", pmax="<<maxPeriodTime<<", bmin="<<minBufferTime<<", bmax="<<maxBufferTime; #endif period_time = minPeriodTime; if (period_time*4 <= maxBufferTime) { // Use 4 periods if possible buffer_time = period_time*4; chunks = 4; } else if (period_time*2 <= maxBufferTime) { // Use 2 periods if possible buffer_time = period_time*2; chunks = 2; } else { qWarning()<<"QAudioOutput: alsa only supports single period!"; fatal = true; } #ifdef DEBUG_AUDIO qDebug()<<"used: buffer_time="<<buffer_time<<", period_time="<<period_time; #endif } } } if ( !fatal ) { err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params: err = %1").arg(err); } } if( err < 0) { qWarning()<<errMessage; errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; return false; } snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames); buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames); snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir); period_size = snd_pcm_frames_to_bytes(handle,period_frames); snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir); snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); // Step 3: Set the desired SW parameters. snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(handle, swparams); snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames); snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames); snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames); snd_pcm_sw_params(handle, swparams); // Step 4: Prepare audio if(audioBuffer == 0) audioBuffer = new char[snd_pcm_frames_to_bytes(handle,buffer_frames)]; snd_pcm_prepare( handle ); snd_pcm_start(handle); // Step 5: Setup callback and timer fallback snd_async_add_pcm_handler(&ahandler, handle, async_callback, this); bytesAvailable = bytesFree(); // Step 6: Start audio processing timer->start(period_time/1000); clockStamp.restart(); timeStamp.restart(); elapsedTimeOffset = 0; errorState = QAudio::NoError; totalTimeValue = 0; opened = true; return true; }
void *Audio_ALSA::open (AudioConfig &cfg, const char *) { AudioConfig tmpCfg; if (_audioHandle != NULL) { _errorString = "ERROR: Device already in use"; return NULL; } #ifdef HAVE_ALSA_ASOUNDLIB_H snd_pcm_uframes_t buffer_frames; snd_pcm_hw_params_t *hw_params = 0; if (snd_pcm_open (&_audioHandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) { _errorString = "ERROR: Could not open audio device."; goto open_error; } // May later be replaced with driver defaults. tmpCfg = cfg; if (snd_pcm_hw_params_malloc (&hw_params)) { _errorString = "ERROR: could not malloc hwparams."; goto open_error; } if (snd_pcm_hw_params_any (_audioHandle, hw_params)) { _errorString = "ERROR: could not initialize hw params"; goto open_error; } if (snd_pcm_hw_params_set_access (_audioHandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) { _errorString = "ERROR: could not set access type"; goto open_error; } snd_pcm_format_t alsamode; switch (tmpCfg.precision) { case 8: tmpCfg.encoding = AUDIO_UNSIGNED_PCM; alsamode = SND_PCM_FORMAT_U8; break; case 16: tmpCfg.encoding = AUDIO_SIGNED_PCM; alsamode = SND_PCM_FORMAT_S16; break; default: _errorString = "ERROR: set desired number of bits for audio device."; goto open_error; } if (snd_pcm_hw_params_set_format (_audioHandle, hw_params, alsamode)) { _errorString = "ERROR: could not set sample format"; goto open_error; } if (snd_pcm_hw_params_set_channels (_audioHandle, hw_params, tmpCfg.channels)) { _errorString = "ERROR: could not set channel count"; goto open_error; } { // Gentoo bug #98769, comment 4 unsigned int rate = tmpCfg.frequency; if (snd_pcm_hw_params_set_rate_near (_audioHandle, hw_params, &rate, 0)) { _errorString = "ERROR: could not set sample rate"; goto open_error; } } _alsa_to_frames_divisor = tmpCfg.channels * tmpCfg.precision / 8; buffer_frames = 4096; snd_pcm_hw_params_set_period_size_near(_audioHandle, hw_params, &buffer_frames, 0); if (snd_pcm_hw_params (_audioHandle, hw_params)) { _errorString = "ERROR: could not set hw parameters"; goto open_error; } snd_pcm_hw_params_free (hw_params); hw_params = 0; if (snd_pcm_prepare (_audioHandle)) { _errorString = "ERROR: could not prepare audio interface for use"; goto open_error; } tmpCfg.bufSize = buffer_frames * _alsa_to_frames_divisor; #else // HAVE_ALSA_ASOUNDLIB_H // Obsolete interface int mask, wantedFormat, format; int rtn; int card = -1, dev = 0; if ((rtn = snd_pcm_open_preferred (&_audioHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK))) { _errorString = "ERROR: Could not open audio device."; goto open_error; } // Transfer input parameters to this object. // May later be replaced with driver defaults. tmpCfg = cfg; snd_pcm_channel_params_t pp; snd_pcm_channel_setup_t setup; snd_pcm_channel_info_t pi; memset (&pi, 0, sizeof (pi)); pi.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_info (_audioHandle, &pi))) { _errorString = "ALSA: snd_pcm_plugin_info failed."; goto open_error; } memset(&pp, 0, sizeof (pp)); pp.mode = SND_PCM_MODE_BLOCK; pp.channel = SND_PCM_CHANNEL_PLAYBACK; pp.start_mode = SND_PCM_START_FULL; pp.stop_mode = SND_PCM_STOP_STOP; pp.buf.block.frag_size = pi.max_fragment_size; pp.buf.block.frags_max = 1; pp.buf.block.frags_min = 1; pp.format.interleave = 1; pp.format.rate = tmpCfg.frequency; pp.format.voices = tmpCfg.channels; // Set sample precision and type of encoding. if ( tmpCfg.precision == 8 ) { tmpCfg.encoding = AUDIO_UNSIGNED_PCM; pp.format.format = SND_PCM_SFMT_U8; } if ( tmpCfg.precision == 16 ) { tmpCfg.encoding = AUDIO_SIGNED_PCM; pp.format.format = SND_PCM_SFMT_S16_LE; } if ((rtn = snd_pcm_plugin_params (_audioHandle, &pp)) < 0) { _errorString = "ALSA: snd_pcm_plugin_params failed."; goto open_error; } if ((rtn = snd_pcm_plugin_prepare (_audioHandle, SND_PCM_CHANNEL_PLAYBACK)) < 0) { _errorString = "ALSA: snd_pcm_plugin_prepare failed."; goto open_error; } memset (&setup, 0, sizeof (setup)); setup.channel = SND_PCM_CHANNEL_PLAYBACK; if ((rtn = snd_pcm_plugin_setup (_audioHandle, &setup)) < 0) { _errorString = "ALSA: snd_pcm_plugin_setup failed."; goto open_error; } tmpCfg.bufSize = setup.buf.block.frag_size; #endif #ifdef HAVE_EXCEPTIONS _sampleBuffer = new(std::nothrow) int_least8_t[tmpCfg.bufSize]; #else _sampleBuffer = new int_least8_t[tmpCfg.bufSize]; #endif if (!_sampleBuffer) { _errorString = "AUDIO: Unable to allocate memory for sample buffers."; goto open_error; } // Setup internal Config _settings = tmpCfg; // Update the users settings getConfig (cfg); return _sampleBuffer; open_error: #ifdef HAVE_ALSA_ASOUNDLIB_H if (hw_params) snd_pcm_hw_params_free (hw_params); #endif if (_audioHandle != NULL) close (); perror ("ALSA"); return NULL; }
int sndout_alsa_start(int rate_, int stereo) { snd_pcm_hw_params_t *hwparams = NULL; unsigned int rate = rate_; int samples, shift; int ret; samples = rate * 40 / 1000; for (shift = 8; (1 << shift) < samples; shift++) ; period_size = 1 << shift; buffer_size = 8 * period_size; snd_pcm_hw_params_alloca(&hwparams); ret = snd_pcm_hw_params_any(handle, hwparams); ret |= snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); ret |= snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE); ret |= snd_pcm_hw_params_set_channels(handle, hwparams, stereo ? 2 : 1); ret |= snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0); ret |= snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size); ret |= snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, NULL); if (ret != 0) { fprintf(stderr, PFX "failed to set hwparams\n"); goto fail; } ret = snd_pcm_hw_params(handle, hwparams); if (ret != 0) { fprintf(stderr, PFX "failed to apply hwparams: %d\n", ret); goto fail; } snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size); snd_pcm_hw_params_get_period_size(hwparams, &period_size, NULL); snd_pcm_hw_params_get_channels(hwparams, &channels); silent_period = realloc(silent_period, period_size * 2 * channels); if (silent_period != NULL) memset(silent_period, 0, period_size * 2 * channels); ret = snd_pcm_prepare(handle); if (ret != 0) { fprintf(stderr, PFX "snd_pcm_prepare failed: %d\n", ret); goto fail; } ret = snd_pcm_start(handle); if (ret != 0) { fprintf(stderr, PFX "snd_pcm_start failed: %d\n", ret); goto fail; } failure_counter = 0; return 0; fail: // to flush out redirected logs fflush(stdout); fflush(stderr); return -1; }
static gboolean alsa_open (void *dp) { alsa_driver * const d = dp; gint mf, err, pers; if(pcm_open_and_load_hwparams(d) < 0) goto out; // --- // Set non-blocking mode. // --- d->outtime = 0; // -- // Set channel parameters // -- if((err = snd_pcm_hw_params_set_access(d->soundfd, d->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){ alsa_error(N_("Unable to set access"), err); goto out; } if((err = snd_pcm_hw_params_set_format(d->soundfd, d->hwparams, (d->bits - 8) ? d->signedness16 ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U16 : d->signedness8 ? SND_PCM_FORMAT_S8 : SND_PCM_FORMAT_U8) < 0)) { alsa_error(N_("Unable to set audio format"), err); goto out; } /* Handle endianess aspects. TODO! */ switch(d->bits) { case 16: mf = d->signedness16 ? ST_MIXER_FORMAT_S16_LE : ST_MIXER_FORMAT_U16_LE; break; case 8: default: mf = d->signedness8 ? ST_MIXER_FORMAT_S8 : ST_MIXER_FORMAT_U8; break; } if((err = snd_pcm_hw_params_set_channels(d->soundfd, d->hwparams, d->stereo + 1)) < 0) { alsa_error(N_("Unable to set channels number"), err); goto out; } if((d->stereo)) { mf |= ST_MIXER_FORMAT_STEREO; } d->mf = mf; d->p_mixfreq = d->playrate; if ((err = snd_pcm_hw_params_set_rate_near(d->soundfd, d->hwparams, &(d->p_mixfreq), NULL)) < 0) { alsa_error(N_("Unable to set sample rate"), err); goto out; } if(snd_pcm_hw_params_set_buffer_size(d->soundfd, d->hwparams, 1 << d->buffer_size) < 0) { /* Some soundcards report wrong maximal buffer size (maybe alsa bug). So we should try to downscale its value before the reporting an error. The spinbutton still may display the wrong number, but actually the correct value will be implemented.*/ while((--d->buffer_size) >= 8) if(!snd_pcm_hw_params_set_buffer_size(d->soundfd, d->hwparams, 1 << d->buffer_size)) break; if(d->buffer_size < 8) { error_error(N_("Unable to set appropriate buffer size")); goto out; } } pers = 1 << d->num_periods; if ((err = snd_pcm_hw_params_set_periods_near(d->soundfd, d->hwparams, &pers, NULL)) < 0) { alsa_error(N_("Unable to set periods number"), err); goto out; } if ((err = snd_pcm_hw_params_get_period_size(d->hwparams, &(d->p_fragsize), NULL)) < 0) { alsa_error(N_("Unable to get period size"), err); goto out; } if((err = snd_pcm_hw_params(d->soundfd, d->hwparams))) { alsa_error(N_("Error setting hw parameters"), err); goto out; } /* The following piece of code is directly c_n_p'ed from the ALSA pcm example (whith a little adopting) */ /* get the current swparams */ err = snd_pcm_sw_params_current(d->soundfd, d->swparams); if (err < 0) { alsa_error(N_("Unable to determine current swparams for playback"), err); goto out; } /* start the transfer when the buffer is full */ err = snd_pcm_sw_params_set_start_threshold(d->soundfd, d->swparams, d->p_fragsize); if (err < 0) { alsa_error(N_("Unable to set start threshold mode for playback"), err); goto out; } /* allow the transfer when at least period_size samples can be processed */ err = snd_pcm_sw_params_set_avail_min(d->soundfd, d->swparams, d->p_fragsize); if (err < 0) { alsa_error(N_("Unable to set avail min for playback"), err); goto out; } /* align all transfers to 1 sample */ err = snd_pcm_sw_params_set_xfer_align(d->soundfd, d->swparams, 1); if (err < 0) { alsa_error(N_("Unable to set transfer align for playback"), err); goto out; } /* write the parameters to the playback device */ err = snd_pcm_sw_params(d->soundfd, d->swparams); if (err < 0) { alsa_error(N_("Unable to set sw params for playback"), err); goto out; } err = snd_pcm_prepare(d->soundfd); if (err < 0) { alsa_error(N_("Unable to prepare playback"), err); goto out; } // --- // Get buffering parameters // --- if(d->verbose) snd_pcm_dump(d->soundfd, d->output); d->sndbuf = calloc((d->stereo + 1) * (d->bits / 8), d->p_fragsize); d->pfd = malloc(sizeof(struct pollfd)); if ((err = snd_pcm_poll_descriptors(d->soundfd, d->pfd, 1)) < 0) { alsa_error(N_("Unable to obtain poll descriptors for playback"), err); goto out; } d->polltag = audio_poll_add(d->pfd->fd, GDK_INPUT_WRITE, alsa_poll_ready_playing, d); d->playtime = 0; d->firstpoll = TRUE; return TRUE; out: alsa_release(dp); return FALSE; }
void alsa_play(void) { struct audio_packet *packet; STREAM out; int len; static long prev_s, prev_us; unsigned int duration; struct timeval tv; int next_tick; if (reopened) { reopened = False; gettimeofday(&tv, NULL); prev_s = tv.tv_sec; prev_us = tv.tv_usec; } /* We shouldn't be called if the queue is empty, but still */ if (rdpsnd_queue_empty()) return; packet = rdpsnd_queue_current_packet(); out = &packet->s; next_tick = rdpsnd_queue_next_tick(); len = (out->end - out->p) / (samplewidth_out * audiochannels_out); if ((len = snd_pcm_writei(out_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0) { printf("Fooo!\n"); snd_pcm_prepare(out_handle); len = 0; } out->p += (len * samplewidth_out * audiochannels_out); gettimeofday(&tv, NULL); duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000; if (packet->tick > next_tick) next_tick += 65536; if ((out->p == out->end) || duration > next_tick - packet->tick + 500) { snd_pcm_sframes_t delay_frames; unsigned long delay_us; prev_s = tv.tv_sec; prev_us = tv.tv_usec; if (abs((next_tick - packet->tick) - duration) > 20) { DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick)); DEBUG(("last: %d, is: %d, should: %d\n", packet->tick, (packet->tick + duration) % 65536, next_tick % 65536)); } if (snd_pcm_delay(out_handle, &delay_frames) < 0) delay_frames = out->size / (samplewidth_out * audiochannels_out); if (delay_frames < 0) delay_frames = 0; delay_us = delay_frames * (1000000 / rate_out); rdpsnd_queue_next(delay_us); } }
static int alsa_write_float (snd_pcm_t *alsa_dev, float *data, int frames, int channels) { static int epipe_count = 0 ; int total = 0 ; int retval ; if (epipe_count > 0) epipe_count -- ; while (total < frames) { retval = snd_pcm_writei (alsa_dev, data + total * channels, frames - total) ; if (retval >= 0) { total += retval ; if (total == frames) return total ; continue ; } ; switch (retval) { case -EAGAIN : puts ("alsa_write_float: EAGAIN") ; continue ; break ; case -EPIPE : if (epipe_count > 0) { printf ("alsa_write_float: EPIPE %d\n", epipe_count) ; if (epipe_count > 140) return retval ; } ; epipe_count += 100 ; #if 0 if (0) { snd_pcm_status_t *status ; snd_pcm_status_alloca (&status) ; if ((retval = snd_pcm_status (alsa_dev, status)) < 0) fprintf (stderr, "alsa_out: xrun. can't determine length\n") ; else if (snd_pcm_status_get_state (status) == SND_PCM_STATE_XRUN) { struct timeval now, diff, tstamp ; gettimeofday (&now, 0) ; snd_pcm_status_get_trigger_tstamp (status, &tstamp) ; timersub (&now, &tstamp, &diff) ; fprintf (stderr, "alsa_write_float xrun: of at least %.3f msecs. resetting stream\n", diff.tv_sec * 1000 + diff.tv_usec / 1000.0) ; } else fprintf (stderr, "alsa_write_float: xrun. can't determine length\n") ; } ; #endif snd_pcm_prepare (alsa_dev) ; break ; case -EBADFD : fprintf (stderr, "alsa_write_float: Bad PCM state.n") ; return 0 ; break ; case -ESTRPIPE : fprintf (stderr, "alsa_write_float: Suspend event.n") ; return 0 ; break ; case -EIO : puts ("alsa_write_float: EIO") ; return 0 ; default : fprintf (stderr, "alsa_write_float: retval = %d\n", retval) ; return 0 ; break ; } ; /* switch */ } ; /* while */ return total ; } /* alsa_write_float */
void *data_streaming(void *socket_desc) { int rc; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; int i; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "plughw:1,0", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 1); /* 44100 bits/second sampling rate (CD quality) */ val = 32768; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = SIZE; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); /* 2 bytes/sample, 2 channels */ /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); while (1) { pthread_mutex_lock(&mutex); rc = snd_pcm_readi(handle, buffer, frames); pthread_kill(tid, SIGUSR1); pthread_mutex_unlock(&mutex); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr,"error from read: %s\n",snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
qint64 QAudioInputPrivate::read(char* data, qint64 len) { // Read in some audio data and write it to QIODevice, pull mode if ( !handle ) return 0; // bytesAvaiable is saved as a side effect of checkBytesReady(). int bytesToRead = checkBytesReady(); if (bytesToRead < 0) { // bytesAvailable as negative is error code, try to recover from it. xrun_recovery(bytesToRead); bytesToRead = checkBytesReady(); if (bytesToRead < 0) { // recovery failed must stop and set error. close(); errorState = QAudio::IOError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); return 0; } } bytesToRead = qMin<qint64>(len, bytesToRead); bytesToRead -= bytesToRead % period_size; int count=0, err = 0; while(count < 5) { int chunks = bytesToRead/period_size; int frames = chunks*period_frames; if(frames > (int)buffer_frames) frames = buffer_frames; int readFrames = snd_pcm_readi(handle, audioBuffer, frames); if (readFrames >= 0) { err = snd_pcm_frames_to_bytes(handle, readFrames); #ifdef DEBUG_AUDIO qDebug()<<QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); #endif break; } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { errorState = QAudio::IOError; err = 0; break; } else { if(readFrames == -EPIPE) { errorState = QAudio::UnderrunError; err = snd_pcm_prepare(handle); } else if(readFrames == -ESTRPIPE) { err = snd_pcm_prepare(handle); } if(err != 0) break; } count++; } if(err > 0) { // got some send it onward #ifdef DEBUG_AUDIO qDebug()<<"frames to write to QIODevice = "<< snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes"; #endif if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return 0; if (pullMode) { qint64 l = audioSource->write(audioBuffer,err); if(l < 0) { close(); errorState = QAudio::IOError; deviceState = QAudio::StoppedState; emit stateChanged(deviceState); } else if(l == 0) { if (deviceState != QAudio::IdleState) { errorState = QAudio::NoError; deviceState = QAudio::IdleState; emit stateChanged(deviceState); } } else { bytesAvailable -= err; totalTimeValue += err; resuming = false; if (deviceState != QAudio::ActiveState) { errorState = QAudio::NoError; deviceState = QAudio::ActiveState; emit stateChanged(deviceState); } } return l; } else { memcpy(data,audioBuffer,err); bytesAvailable -= err; totalTimeValue += err; resuming = false; if (deviceState != QAudio::ActiveState) { errorState = QAudio::NoError; deviceState = QAudio::ActiveState; emit stateChanged(deviceState); } return err; } } return 0; }