void alsa_start(struct alsa_dev *dev) { short *pcm; size_t len = dev->period * dev->channels; pcm = xzmalloc(len * sizeof(*pcm)); alsa_write(dev, pcm, dev->period); alsa_write(dev, pcm, dev->period); xfree(pcm); snd_pcm_start(dev->capture_handle); snd_pcm_start(dev->playback_handle); }
qint64 OutputALSA::writeAudio(unsigned char *data, qint64 maxSize) { if((maxSize = qMin(maxSize, m_prebuf_size - m_prebuf_fill)) > 0) { memmove(m_prebuf + m_prebuf_fill, data, maxSize); m_prebuf_fill += maxSize; } snd_pcm_uframes_t l = snd_pcm_bytes_to_frames(pcm_handle, m_prebuf_fill); while (l >= m_chunk_size) { snd_pcm_wait(pcm_handle, 10); long m; if ((m = alsa_write(m_prebuf, m_chunk_size)) >= 0) { l -= m; m = snd_pcm_frames_to_bytes(pcm_handle, m); // convert frames to bytes m_prebuf_fill -= m; memmove(m_prebuf, m_prebuf + m, m_prebuf_fill); //move data to begin } else return -1; } return maxSize; }
void alsa_write_process(MSFilter *obj){ AlsaWriteData *ad=(AlsaWriteData*)obj->data; mblk_t *im=NULL; int size; int samples; int err; if (ad->handle==NULL && ad->pcmdev!=NULL){ ad->handle=alsa_open_w(ad->pcmdev,16,ad->nchannels==2,ad->rate); #ifdef EPIPE_BUGFIX alsa_fill_w (ad->pcmdev); #endif } if (ad->handle==NULL) { ms_queue_flush(obj->inputs[0]); return; } while ((im=ms_queue_get(obj->inputs[0]))!=NULL){ while((size=im->b_wptr-im->b_rptr)>0){ samples=size/(2*ad->nchannels); err=alsa_write(ad->handle,im->b_rptr,samples); if (err>0) { im->b_rptr+=err*(2*ad->nchannels); } else break; } freemsg(im); } }
void usb_xfer_done(struct libusb_transfer *xfer) { uint8_t *data = xfer->buffer; int datalen = xfer->actual_length; reads_pending -= 1; alsa_write(data, datalen); free(data); libusb_free_transfer(xfer); usb_initiate_transfer(); }
int sound_write(int16_t **bf, int *nbf, int outp) { switch (outp) { case ALSA: return alsa_write(bf, nbf); break; case DSP: return dsp_write(bf, nbf); break; case STDOUT: return stdout_write(bf, nbf); break; default: fprintf(stderr, "Unknown output method\n"); } return -1; }
void OutputALSA::drain() { long m = 0; snd_pcm_uframes_t l = snd_pcm_bytes_to_frames(pcm_handle, m_prebuf_fill); while (l > 0) { if ((m = alsa_write(m_prebuf, l)) >= 0) { l -= m; m = snd_pcm_frames_to_bytes(pcm_handle, m); // convert frames to bytes m_prebuf_fill -= m; memmove(m_prebuf, m_prebuf + m, m_prebuf_fill); } else break; } snd_pcm_nonblock(pcm_handle, 0); snd_pcm_drain(pcm_handle); snd_pcm_nonblock(pcm_handle, 1); }
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; }
int write_local_sound(unsigned char* samples) { int i; static bool do_once = true; static int in_count = 0; int insert = 0; if (do_once) { if (in_count++ > alsa_cb.thread_buffer_time) do_once = false; if (in_count > alsa_cb.thread_buffer_time / 2 && in_count < alsa_cb.thread_buffer_time) return 0; } for(i = 8; i < 512; i += 8) { //bytes are L,R,I,Q skip the I,Q alsa_cb.buffer[insert++] = samples[i]; //left alsa_cb.buffer[insert++] = samples[i + 1]; alsa_cb.buffer[insert++] = samples[i + 2]; //right alsa_cb.buffer[insert++] = samples[i + 3]; } for(i = 520; i < 1024; i += 8) { alsa_cb.buffer[insert++] = samples[i]; alsa_cb.buffer[insert++] = samples[i + 1]; alsa_cb.buffer[insert++] = samples[i + 2]; alsa_cb.buffer[insert++] = samples[i + 3]; } alsa_write(alsa_cb.buffer, 504); #if 0 // test the audio sample rate { struct timeb start_time; struct timeb end_time; static int sample_count = 0; static float rate = 0.0; static float rate_count = 0.0; sample_count+=504; if(sample_count >= 48000) { ftime(&end_time); // skip the 1st one, it's bogus if (0.0 == rate_count) { rate_count = 1; sample_count = 0; ftime(&start_time); return 0; } rate += (float)((sample_count*1000/4) /(((end_time.time*1000)+end_time.millitm)- ((start_time.time*1000)+start_time.millitm))); printf("sample rate avg: %.1f/sec\n", rate / rate_count); sample_count=0; rate_count += 1.0; ftime(&start_time); } } #endif return 0; }