static gboolean gst_alsasink_unprepare (GstAudioSink * asink) { GstAlsaSink *alsa; gint err; alsa = GST_ALSA_SINK (asink); CHECK (snd_pcm_drop (alsa->handle), drop); CHECK (snd_pcm_hw_free (alsa->handle), hw_free); return TRUE; /* ERRORS */ drop: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Could not drop samples: %s", snd_strerror (err))); return FALSE; } hw_free: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Could not free hw params: %s", snd_strerror (err))); return FALSE; } }
static int snd_pcm_file_hw_free(snd_pcm_t *pcm) { snd_pcm_file_t *file = pcm->private_data; free(file->wbuf); free(file->wbuf_areas); file->wbuf = NULL; file->wbuf_areas = NULL; return snd_pcm_hw_free(file->gen.slave); }
static gboolean gst_alsasink_unprepare (GstAudioSink * asink) { GstAlsaSink *alsa; alsa = GST_ALSA_SINK (asink); snd_pcm_drop (alsa->handle); snd_pcm_hw_free (alsa->handle); return TRUE; }
static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc) { GstAlsaSrc *alsa; alsa = GST_ALSA_SRC (asrc); snd_pcm_drop (alsa->handle); snd_pcm_hw_free (alsa->handle); snd_pcm_nonblock (alsa->handle, 1); return TRUE; }
int snd_pcm_close(snd_pcm_t *pcm) { if (pcm->setup) { snd_pcm_drop(pcm); snd_pcm_hw_free(pcm); } _snd_pcm_munmap(pcm); snd_pcm_hw_munmap_status(pcm); #if SALSA_HAS_ASYNC_SUPPORT if (pcm->async) snd_async_del_handler(pcm->async); #endif close(pcm->fd); free(pcm); return 0; }
/** Fills the input buffer with audio data from the microphone. * * @param data the buffer to fill with audio data * @param len the size of the buffer * @return a pointer to the filled buffer */ uint16_t VoiceStreamer::fillBuffer(char *data, int len) { int latency, bufsize, room_left = len; size_t frames_in, frames_out, in_max; ssize_t r; char *buffer, *data_ptr = data; bool done = false; latency = latency_min - 4; bufsize = (latency_max*snd_pcm_format_width(format)/8)*2; buffer = new char[bufsize]; while (!done) { while (frames_in < loop_limit) { if ((r = readbuf(chandle, buffer, latency, &frames_in, &in_max)) < 0) { break; } else { if (room_left > r<<2) { memcpy(data_ptr, buffer, r<<2); data_ptr += (r<<2); room_left -= (r<<2); } else { memcpy(data_ptr, buffer, room_left); data_ptr += room_left; room_left = 0; done = true; break; } } } if (!done) { snd_pcm_drop(chandle); snd_pcm_unlink(chandle); snd_pcm_hw_free(chandle); frames_in = frames_out = in_max = 0; if (setparams_c(chandle, &latency) < 0) break; } } return uint16_t (len - room_left); }
int snd_pcm_generic_hw_free(snd_pcm_t *pcm) { snd_pcm_generic_t *generic = pcm->private_data; return snd_pcm_hw_free(generic->slave); }
int main(int argc, char *argv[]) { struct option long_option[] = { {"help", 0, NULL, 'h'}, {"pdevice", 1, NULL, 'P'}, {"cdevice", 1, NULL, 'C'}, {"min", 1, NULL, 'm'}, {"max", 1, NULL, 'M'}, {"frames", 1, NULL, 'F'}, {"format", 1, NULL, 'f'}, {"channels", 1, NULL, 'c'}, {"rate", 1, NULL, 'r'}, {"seconds", 1, NULL, 's'}, {"block", 0, NULL, 'b'}, {"time", 1, NULL, 't'}, {"poll", 0, NULL, 'p'}, {"effect", 0, NULL, 'e'}, {NULL, 0, NULL, 0}, }; snd_pcm_t *phandle, *chandle; char *buffer; int err, latency, morehelp; int ok; snd_timestamp_t p_tstamp, c_tstamp; ssize_t r; size_t frames_in, frames_out, in_max; int effect = 0; morehelp = 0; while (1) { int c; if ((c = getopt_long(argc, argv, "hP:C:m:M:F:f:c:r:s:bt:pe", long_option, NULL)) < 0) break; switch (c) { case 'h': morehelp++; break; case 'P': pdevice = strdup(optarg); break; case 'C': cdevice = strdup(optarg); break; case 'm': err = atoi(optarg) / 2; latency_min = err >= 4 ? err : 4; if (latency_max < latency_min) latency_max = latency_min; break; case 'M': err = atoi(optarg) / 2; latency_max = latency_min > err ? latency_min : err; break; case 'f': format = snd_pcm_format_value(optarg); if (format == SND_PCM_FORMAT_UNKNOWN) { printf("Unknown format, setting to default S16_LE\n"); format = SND_PCM_FORMAT_S16_LE; } break; case 'c': err = atoi(optarg); channels = err >= 1 && err < 1024 ? err : 1; break; case 'r': err = atoi(optarg); rate = err >= 4000 && err < 200000 ? err : 44100; break; case 's': err = atoi(optarg); loop_sec = err >= 1 && err <= 100000 ? err : 30; break; case 'b': block = 1; break; case 't': tick_time = atoi(optarg); tick_time = tick_time < 0 ? 0 : tick_time; break; case 'p': use_poll = 1; break; case 'e': effect = 1; break; } } if (morehelp) { help(); return 0; } err = snd_output_stdio_attach(&output, stdout, 0); if (err < 0) { printf("Output failed: %s\n", snd_strerror(err)); return 0; } loop_limit = loop_sec * rate; latency = latency_min - 4; buffer = malloc((latency_max * snd_pcm_format_width(format) / 8) * 2); setscheduler(); printf("Playback device is %s\n", pdevice); printf("Capture device is %s\n", cdevice); printf("Parameters are %iHz, %s, %i channels, %s mode\n", rate, snd_pcm_format_name(format), channels, block ? "blocking" : "non-blocking"); printf("Wanted tick time: %ius, poll mode: %s\n", tick_time, use_poll ? "yes" : "no"); printf("Loop limit is %li frames, minimum latency = %i, maximum latency = %i\n", loop_limit, latency_min * 2, latency_max * 2); if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK)) < 0) { printf("Playback open error: %s\n", snd_strerror(err)); return 0; } if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE, block ? 0 : SND_PCM_NONBLOCK)) < 0) { printf("Record open error: %s\n", snd_strerror(err)); return 0; } /* initialize the filter sweep variables */ if (effect) { fs = (float) rate; BW = FILTER_BANDWIDTH; lfo = 0; dlfo = 2.*M_PI*FILTERSWEEP_LFO_FREQ/fs; x[0] = (float*) malloc(channels*sizeof(float)); x[1] = (float*) malloc(channels*sizeof(float)); x[2] = (float*) malloc(channels*sizeof(float)); y[0] = (float*) malloc(channels*sizeof(float)); y[1] = (float*) malloc(channels*sizeof(float)); y[2] = (float*) malloc(channels*sizeof(float)); } while (1) { frames_in = frames_out = 0; if (setparams(phandle, chandle, &latency) < 0) break; showlatency(latency); if (tick_time_ok) printf("Using tick time %ius\n", tick_time_ok); if ((err = snd_pcm_link(chandle, phandle)) < 0) { printf("Streams link error: %s\n", snd_strerror(err)); exit(0); } if (snd_pcm_format_set_silence(format, buffer, latency*channels) < 0) { fprintf(stderr, "silence error\n"); break; } if (writebuf(phandle, buffer, latency, &frames_out) < 0) { fprintf(stderr, "write error\n"); break; } if (writebuf(phandle, buffer, latency, &frames_out) < 0) { fprintf(stderr, "write error\n"); break; } if ((err = snd_pcm_start(chandle)) < 0) { printf("Go error: %s\n", snd_strerror(err)); exit(0); } gettimestamp(phandle, &p_tstamp); gettimestamp(chandle, &c_tstamp); #if 0 printf("Playback:\n"); showstat(phandle, frames_out); printf("Capture:\n"); showstat(chandle, frames_in); #endif ok = 1; in_max = 0; while (ok && frames_in < loop_limit) { if (use_poll) { /* use poll to wait for next event */ snd_pcm_wait(chandle, 1000); } if ((r = readbuf(chandle, buffer, latency, &frames_in, &in_max)) < 0) ok = 0; else { if (effect) applyeffect(buffer,r); if (writebuf(phandle, buffer, r, &frames_out) < 0) ok = 0; } } if (ok) printf("Success\n"); else printf("Failure\n"); printf("Playback:\n"); showstat(phandle, frames_out); printf("Capture:\n"); showstat(chandle, frames_in); showinmax(in_max); if (p_tstamp.tv_sec == p_tstamp.tv_sec && p_tstamp.tv_usec == c_tstamp.tv_usec) printf("Hardware sync\n"); snd_pcm_drop(chandle); snd_pcm_nonblock(phandle, 0); snd_pcm_drain(phandle); snd_pcm_nonblock(phandle, !block ? 1 : 0); if (ok) { #if 1 printf("Playback time = %li.%i, Record time = %li.%i, diff = %li\n", p_tstamp.tv_sec, (int)p_tstamp.tv_usec, c_tstamp.tv_sec, (int)c_tstamp.tv_usec, timediff(p_tstamp, c_tstamp)); #endif break; } snd_pcm_unlink(chandle); snd_pcm_hw_free(phandle); snd_pcm_hw_free(chandle); } snd_pcm_close(phandle); snd_pcm_close(chandle); return 0; }
static int alsa_stream(const char *pdevice, const char *cdevice, int latency) { snd_pcm_t *phandle, *chandle; char *buffer; int err; ssize_t r; struct final_params negotiated; snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; char pdevice_new[32]; err = snd_output_stdio_attach(&output, error_fp, 0); if (err < 0) { fprintf(error_fp, "alsa: Output failed: %s\n", snd_strerror(err)); return 0; } /* Open the devices */ if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(error_fp, "alsa: Cannot open playback device %s: %s\n", pdevice, snd_strerror(err)); return 0; } if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) { fprintf(error_fp, "alsa: Cannot open capture device %s: %s\n", cdevice, snd_strerror(err)); snd_pcm_close(phandle); return 0; } err = setparams(phandle, chandle, format, latency, 0, &negotiated); /* Try to use plughw instead, as it allows emulating speed */ if (err == 2 && strncmp(pdevice, "hw", 2) == 0) { snd_pcm_close(phandle); sprintf(pdevice_new, "plug%s", pdevice); pdevice = pdevice_new; if (verbose) fprintf(error_fp, "alsa: Trying %s for playback\n", pdevice); if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(error_fp, "alsa: Cannot open playback device %s: %s\n", pdevice, snd_strerror(err)); snd_pcm_close(chandle); return 0; } err = setparams(phandle, chandle, format, latency, 1, &negotiated); } if (err != 0) { fprintf(error_fp, "alsa: setparams failed\n"); snd_pcm_close(phandle); snd_pcm_close(chandle); return 1; } buffer = malloc((negotiated.bufsize * snd_pcm_format_width(format) / 8) * negotiated.channels); if (buffer == NULL) { fprintf(error_fp, "alsa: Failed allocating buffer for audio\n"); snd_pcm_close(phandle); snd_pcm_close(chandle); return 0; } if (verbose) fprintf(error_fp, "alsa: stream started from %s to %s (%i Hz, buffer delay = %.2f ms)\n", cdevice, pdevice, negotiated.rate, negotiated.latency * 1000.0 / negotiated.rate); while (!stop_alsa) { /* We start with a read and not a wait to auto(re)start the capture */ r = readbuf(chandle, buffer, negotiated.bufsize); if (r == 0) /* Succesfully recovered from an overrun? */ continue; /* Force restart of capture stream */ if (r > 0) writebuf(phandle, buffer, r); /* use poll to wait for next event */ while (!stop_alsa && !snd_pcm_wait(chandle, 50)) ; } snd_pcm_drop(chandle); snd_pcm_drop(phandle); snd_pcm_unlink(chandle); snd_pcm_hw_free(phandle); snd_pcm_hw_free(chandle); snd_pcm_close(phandle); snd_pcm_close(chandle); return 0; }
/** Plays the audio contained packets queue that is filled by the * chatting thread with received packets. */ void VoiceStreamer::playbackAudio() { int data_left, r; packet audioPacket; uint8_t *data_ptr; bool done = false; int pLatency = latency_min - 4; size_t pframes_in, pframes_out, pin_max; // Init playback device if (setparams_p(phandle, &pLatency) < 0) { fprintf(stderr, "Playback Audio Thread: exiting due to setparams_p error\n"); return; } pframes_in = pframes_out = 0; pin_max = 0; while (true) { if (!popAudioPacket(audioPacket)) break; data_ptr = audioPacket.data; data_left = (int) ntohs(audioPacket.dlength); while (pframes_in < loop_limit) { if (data_left > (pLatency<<2)) r = pLatency; else r = data_left>>2; if (r > 0) { pframes_in += r; if ((int) pin_max < r) pin_max = r; if (writebuf(phandle, (char *) data_ptr, r, &pframes_out) < 0) { break; } } else if (r == 0) { // done reading input file done = true; break; } else { break; } if (data_left > (pLatency<<2)) { data_ptr += (pLatency<<2); data_left -= (pLatency<<2); } else { data_ptr += data_left; data_left = 0; } } if (!done) { done = false; snd_pcm_nonblock(phandle, 0); snd_pcm_drain(phandle); snd_pcm_hw_free(phandle); pframes_in = pframes_out = pin_max = 0; if (setparams_p(phandle, &pLatency) < 0) { fprintf(stderr, "setparams_p < 0!\n"); break; } } } startPlayback = false; fprintf(stderr, "Playback Audio Thread exitting!\n"); }