void audio_send_tone(wave_type_t type, unsigned int hz) { unsigned* waveform; if (type == WAVE_TRIANGLE) { waveform = waveform_triangle; } else if (type == WAVE_SINE) { waveform = waveform_sine; } else if (type == WAVE_SAW) { waveform = waveform_saw; } else { waveform = waveform_square; } if (audio_set_clock(hz)) { // Start the clock // enable (ENAB) + oscillator // raspbian has this as plla *(clk + BCM2835_PWMCLK_CNTL) = PM_PASSWORD | BCM2835_CM_ENAB | BCM2835_CM_OSCILLATOR; delay_us(2000); // disable PWM *(pwm + BCM2835_PWM_CONTROL) = 0; delay_us(2000); // We are dividing each "step" of the sinusoid into 128 // pulse slots. *(pwm+BCM2835_PWM0_RANGE) = 0x80; *(pwm+BCM2835_PWM1_RANGE) = 0x80; // Re-enable PWM *(pwm+BCM2835_PWM_CONTROL) = BCM2835_PWM1_USEFIFO | BCM2835_PWM1_ENABLE | BCM2835_PWM0_USEFIFO | BCM2835_PWM0_ENABLE | 1 << 6; // Clear the FIFO of any old data delay_us(2000); int i = 0; while(1) { int status = *(pwm + BCM2835_PWM_STATUS); if (!(status & BCM2835_FULL1)) { *(pwm+BCM2835_PWM_FIFO) = waveform[i]; i++; i = i % 64; } if ((status & ERRORMASK)) { *(pwm+BCM2835_PWM_STATUS) = ERRORMASK; } } } }
static void * dummy_audio_thread(void *aux) { audio_decoder_t *ad = aux; media_pipe_t *mp = ad->ad_mp; media_queue_t *mq = &mp->mp_audio; media_buf_t *mb; int hold = 0; int run = 1; int64_t rt = 0; int64_t base = AV_NOPTS_VALUE; hts_mutex_lock(&mp->mp_mutex); while(run) { if((mb = TAILQ_FIRST(&mq->mq_q)) == NULL) { hts_cond_wait(&mq->mq_avail, &mp->mp_mutex); continue; } if(mb->mb_data_type == MB_AUDIO && hold && mb->mb_skip == 0) { hts_cond_wait(&mq->mq_avail, &mp->mp_mutex); continue; } TAILQ_REMOVE(&mq->mq_q, mb, mb_link); mq->mq_packets_current--; mp->mp_buffer_current -= mb->mb_size; mq_update_stats(mp, mq); hts_cond_signal(&mp->mp_backpressure); hts_mutex_unlock(&mp->mp_mutex); switch(mb->mb_data_type) { case MB_CTRL_EXIT: run = 0; break; case MB_CTRL_PAUSE: hold = 1; break; case MB_CTRL_PLAY: hold = 0; base = AV_NOPTS_VALUE; break; case MB_FLUSH: base = AV_NOPTS_VALUE; break; case MB_AUDIO: if(mb->mb_skip || mb->mb_stream != mq->mq_stream) break; if(mb->mb_pts != AV_NOPTS_VALUE) { audio_set_clock(mp, mb->mb_pts, 0, mb->mb_epoch); if(base == AV_NOPTS_VALUE) { base = mb->mb_pts; rt = showtime_get_ts(); } else { int64_t d = mb->mb_pts - base; if(d > 0) { int sleeptime = rt + d - showtime_get_ts(); if(sleeptime > 0) usleep(sleeptime); } } } break; default: abort(); } hts_mutex_lock(&mp->mp_mutex); media_buf_free_locked(mp, mb); } hts_mutex_unlock(&mp->mp_mutex); return NULL; }