static void alsa_play (int argc, char *argv []) { static float buffer [BUFFER_LEN] ; SNDFILE *sndfile ; SF_INFO sfinfo ; snd_pcm_t * alsa_dev ; int k, readcount, subformat ; for (k = 1 ; k < argc ; k++) { memset (&sfinfo, 0, sizeof (sfinfo)) ; printf ("Playing %s\n", argv [k]) ; if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo))) { puts (sf_strerror (NULL)) ; continue ; } ; if (sfinfo.channels < 1 || sfinfo.channels > 2) { printf ("Error : channels = %d.\n", sfinfo.channels) ; continue ; } ; if ((alsa_dev = alsa_open (sfinfo.channels, (unsigned) sfinfo.samplerate, SF_FALSE)) == NULL) continue ; subformat = sfinfo.format & SF_FORMAT_SUBMASK ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) { double scale ; int m ; sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ; if (scale < 1e-10) scale = 1.0 ; else scale = 32700.0 / scale ; while ((readcount = sf_read_float (sndfile, buffer, BUFFER_LEN))) { for (m = 0 ; m < readcount ; m++) buffer [m] *= scale ; alsa_write_float (alsa_dev, buffer, BUFFER_LEN / sfinfo.channels, sfinfo.channels) ; } ; } else { while ((readcount = sf_read_float (sndfile, buffer, BUFFER_LEN))) alsa_write_float (alsa_dev, buffer, BUFFER_LEN / sfinfo.channels, sfinfo.channels) ; } ; snd_pcm_drain (alsa_dev) ; snd_pcm_close (alsa_dev) ; sf_close (sndfile) ; } ; return ; } /* alsa_play */
void sound_open(int outp) { switch (outp) { case ALSA: alsa_open(DEVALSA); break; case DSP: dsp_open(DEVDSP); break; case STDOUT: stdout_open(DEVDSP); break; default: fprintf(stderr, "Unknown output method\n"); } }
static void* alsa_audio_start(void *aux) { audio_fifo_t *af = aux; snd_pcm_t *h = NULL; int c; int cur_channels = 0; int cur_rate = 0; audio_fifo_data_t *afd; for (;;) { afd = audio_get(af); if (!h || cur_rate != afd->rate || cur_channels != afd->channels) { if (h) snd_pcm_close(h); cur_rate = afd->rate; cur_channels = afd->channels; h = alsa_open("default", cur_rate, cur_channels); if (!h) { fprintf(stderr, "Unable to open ALSA device (%d channels, %d Hz), dying\n", cur_channels, cur_rate); exit(1); } } c = snd_pcm_wait(h, 1000); if (c >= 0) c = snd_pcm_avail_update(h); if (c == -EPIPE) snd_pcm_prepare(h); snd_pcm_writei(h, afd->samples, afd->nsamples); writeFile( &afd->samples ); zfree(afd); } }
struct audio_oops* setup_alsa(const char *dev, const char *ctl) { static int init_complete = 0; if(dev && strlen(dev) > 0) { device = strdup(dev); } else { device = strdup("plughw:0,0"); /* playback device */ } if(init_complete) { ERRORLOG("already initialized\n"); return NULL; } if(!alsa_open()) init_complete = 1; else return NULL; return &alsa_oops; }
static void *playback_thread(void *cr) { struct _crad_t *p_crad = (struct _crad_t *)cr; snd_pcm_uframes_t playback_size, recording_size; snd_pcm_t *playback, *recording; alsa_open(&recording, SND_PCM_STREAM_CAPTURE, &recording_size); alsa_open(&playback, SND_PCM_STREAM_PLAYBACK, &playback_size); snd_pcm_start(recording); snd_pcm_uframes_t recording_data[recording_size]; while(p_crad->playback_thread_running) { // Figure out how many frames to read. Take the minimum // available frames between playback and recording. int recording_avail = snd_pcm_avail_update(recording); int playback_avail = snd_pcm_avail_update(playback); int frames_to_read; if(recording_avail < playback_avail) frames_to_read = recording_avail; else frames_to_read = playback_avail; // If we have less than 10ms of data, pause for 5ms and try again. if(frames_to_read < 441) { usleep(5000); continue; } int frames_read = snd_pcm_readi(recording, recording_data, frames_to_read); // If we didn't get enough data, wait, then try again. if(frames_read == -EAGAIN) { fprintf(stderr, "Read error, trying again: %s\n", snd_strerror(frames_read)); continue; } else if(frames_read == -EPIPE) { fprintf(stderr, "Read error: Overrun\n"); if(alsa_recover(recording)) { p_crad->playback_thread_running = 0; break; } continue; } // Or if we had a different error, bail. else if(frames_read < 0) { fprintf(stderr, "Read error: %s\n", snd_strerror(frames_read)); p_crad->playback_thread_running = 0; break; } while(frames_read > 0) { int frames_written; frames_written = snd_pcm_writei(playback, recording_data, frames_read); if(frames_written == -EPIPE) { fprintf(stderr, "Write error: Underrun\n"); if(alsa_recover(playback)) { p_crad->playback_thread_running = 0; break; } continue; } else if(frames_written <= 0) { fprintf(stderr, "Write error (%d): %s\n", frames_written, snd_strerror(frames_written)); p_crad->playback_thread_running = 0; break; } else { frames_read -= frames_written; } } } error: fprintf(stderr, "Quitting audio playback thread...\n"); //snd_pcm_drain(recording); snd_pcm_close(recording); //snd_pcm_drain(playback); snd_pcm_close(playback); pthread_exit(NULL); }
int main(int argc, char **argv) { int sd, rc, n, tmp; char msg[MAX_MSG]; int nfds; int send_timestamp = 0; int recv_started = 0; struct pollfd *pfds; struct alsa_dev *dev; CELTEncoder *enc_state; CELTDecoder *dec_state; CELTMode *mode; struct sched_param param; JitterBuffer *jitter; SpeexEchoState *echo_state; char mac_own[6], mac_remote[6]; if (argc != 4) panic("Usage %s plughw:0,0 <lmac in xx:xx:xx:xx:xx:xx> <rmac>\n", argv[0]); register_signal(SIGINT, sighandler); hack_mac(mac_own, argv[2], strlen(argv[2])); hack_mac(mac_remote, argv[3], strlen(argv[3])); sd = socket(AF_LANA, SOCK_RAW, 0); if (sd < 0) panic("%s: cannot open socket \n", argv[0]); printf("If ready hit key!\n"); //user must do binding getchar(); dev = alsa_open(argv[1], SAMPLING_RATE, CHANNELS, FRAME_SIZE); mode = celt_mode_create(SAMPLING_RATE, FRAME_SIZE, NULL); enc_state = celt_encoder_create(mode, CHANNELS, NULL); dec_state = celt_decoder_create(mode, CHANNELS, NULL); param.sched_priority = sched_get_priority_min(SCHED_FIFO); if (sched_setscheduler(0, SCHED_FIFO, ¶m)) whine("sched_setscheduler error!\n"); /* Setup all file descriptors for poll()ing */ nfds = alsa_nfds(dev); pfds = xmalloc(sizeof(*pfds) * (nfds + 1)); alsa_getfds(dev, pfds, nfds); pfds[nfds].fd = sd; pfds[nfds].events = POLLIN; /* Setup jitter buffer using decoder */ jitter = jitter_buffer_init(FRAME_SIZE); tmp = FRAME_SIZE; jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MARGIN, &tmp); /* Echo canceller with 200 ms tail length */ echo_state = speex_echo_state_init(FRAME_SIZE, 10 * FRAME_SIZE); tmp = SAMPLING_RATE; speex_echo_ctl(echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp); register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); alsa_start(dev); printf("ALSA started!\n"); itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); while (!sigint) { poll(pfds, nfds + 1, -1); /* Received packets */ if (pfds[nfds].revents & POLLIN) { memset(msg, 0, MAX_MSG); n = recv(sd, msg, MAX_MSG, 0); if (n <= 0) goto do_alsa; pkts_in++; int recv_timestamp; memcpy(&recv_timestamp, msg, sizeof(recv_timestamp)); JitterBufferPacket packet; packet.data = msg+4/*+6+6+2*/; packet.len = n-4/*-6-6-2*/; packet.timestamp = recv_timestamp; packet.span = FRAME_SIZE; packet.sequence = 0; /* Put content of the packet into the jitter buffer, except for the pseudo-header */ jitter_buffer_put(jitter, &packet); recv_started = 1; } do_alsa: /* Ready to play a frame (playback) */ if (alsa_play_ready(dev, pfds, nfds)) { short pcm[FRAME_SIZE * CHANNELS] = {0}; if (recv_started) { JitterBufferPacket packet; /* Get audio from the jitter buffer */ packet.data = msg; packet.len = MAX_MSG; jitter_buffer_tick(jitter); jitter_buffer_get(jitter, &packet, FRAME_SIZE, NULL); if (packet.len == 0) packet.data=NULL; celt_decode(dec_state, (const unsigned char *) packet.data, packet.len, pcm); } /* Playback the audio and reset the echo canceller if we got an underrun */ alsa_write(dev, pcm, FRAME_SIZE); // if (alsa_write(dev, pcm, FRAME_SIZE)) // speex_echo_state_reset(echo_state); /* Put frame into playback buffer */ // speex_echo_playback(echo_state, pcm); } /* Audio available from the soundcard (capture) */ if (alsa_cap_ready(dev, pfds, nfds)) { short pcm[FRAME_SIZE * CHANNELS]; //pcm2[FRAME_SIZE * CHANNELS]; char outpacket[MAX_MSG]; alsa_read(dev, pcm, FRAME_SIZE); /* Perform echo cancellation */ // speex_echo_capture(echo_state, pcm, pcm2); // for (i = 0; i < FRAME_SIZE * CHANNELS; ++i) // pcm[i] = pcm2[i]; celt_encode(enc_state, pcm, NULL, (unsigned char *) (outpacket+4+6+6+2), PACKETSIZE); /* Pseudo header: four null bytes and a 32-bit timestamp; XXX hack */ memcpy(outpacket,mac_remote,6); memcpy(outpacket+6,mac_own,6); outpacket[6+6] = (uint8_t) 0xac; outpacket[6+6+1] = (uint8_t) 0xdc; memcpy(outpacket+6+6+2, &send_timestamp, sizeof(send_timestamp)); send_timestamp += FRAME_SIZE; rc = sendto(sd, outpacket, PACKETSIZE+4+6+6+2, 0, NULL, 0); if (rc < 0) panic("cannot send to socket"); pkts_out++; } } itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itimer, NULL); close(sd); return 0; }
void open_local_sound(char* adevice) { alsa_init(adevice); alsa_open(48000, 2, 8192); }