summaryrefslogtreecommitdiff
path: root/apps/pcmbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/pcmbuf.c')
-rw-r--r--apps/pcmbuf.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index 691f8d5a19..5f78901a56 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -34,6 +34,7 @@
34#include "buffer.h" 34#include "buffer.h"
35#include "settings.h" 35#include "settings.h"
36#include "audio.h" 36#include "audio.h"
37#include "dsp.h"
37 38
38#define CHUNK_SIZE PCMBUF_GUARD 39#define CHUNK_SIZE PCMBUF_GUARD
39/* Must be a power of 2 */ 40/* Must be a power of 2 */
@@ -86,9 +87,11 @@ struct pcmbufdesc
86volatile int pcmbuf_read_index; 87volatile int pcmbuf_read_index;
87volatile int pcmbuf_write_index; 88volatile int pcmbuf_write_index;
88int pcmbuf_unplayed_bytes; 89int pcmbuf_unplayed_bytes;
90int pcmbuf_mix_used_bytes;
89int pcmbuf_watermark; 91int pcmbuf_watermark;
90void (*pcmbuf_watermark_event)(int bytes_left); 92void (*pcmbuf_watermark_event)(int bytes_left);
91static int last_chunksize; 93static int last_chunksize;
94static long mixpos = 0;
92 95
93static void pcmbuf_boost(bool state) 96static void pcmbuf_boost(bool state)
94{ 97{
@@ -173,6 +176,7 @@ bool pcmbuf_add_chunk(void *addr, int size, void (*callback)(void))
173 pcmbuffers[pcmbuf_write_index].callback = callback; 176 pcmbuffers[pcmbuf_write_index].callback = callback;
174 pcmbuf_write_index = (pcmbuf_write_index+1) & NUM_PCM_BUFFERS_MASK; 177 pcmbuf_write_index = (pcmbuf_write_index+1) & NUM_PCM_BUFFERS_MASK;
175 pcmbuf_unplayed_bytes += size; 178 pcmbuf_unplayed_bytes += size;
179 pcmbuf_mix_used_bytes = MAX(0, pcmbuf_mix_used_bytes - size);
176 return true; 180 return true;
177 } 181 }
178 else 182 else
@@ -254,6 +258,7 @@ void pcmbuf_play_stop(void)
254 pcm_play_stop(); 258 pcm_play_stop();
255 last_chunksize = 0; 259 last_chunksize = 0;
256 pcmbuf_unplayed_bytes = 0; 260 pcmbuf_unplayed_bytes = 0;
261 pcmbuf_mix_used_bytes = 0;
257 pcmbuf_read_index = 0; 262 pcmbuf_read_index = 0;
258 pcmbuf_write_index = 0; 263 pcmbuf_write_index = 0;
259 audiobuffer_pos = 0; 264 audiobuffer_pos = 0;
@@ -297,6 +302,13 @@ void pcmbuf_flush_audio(void)
297 crossfade_init = true; 302 crossfade_init = true;
298} 303}
299 304
305/* Force playback. */
306void pcmbuf_play_start(void)
307{
308 if (!pcm_is_playing() && pcmbuf_unplayed_bytes)
309 pcm_play_data(pcmbuf_callback);
310}
311
300void pcmbuf_flush_fillpos(void) 312void pcmbuf_flush_fillpos(void)
301{ 313{
302 int copy_n; 314 int copy_n;
@@ -562,6 +574,98 @@ bool pcmbuf_insert_buffer(char *buf, long length)
562 return true; 574 return true;
563} 575}
564 576
577/* Generates a constant square wave sound with a given frequency
578 in Hertz for a duration in milliseconds. */
579void pcmbuf_beep(int frequency, int duration, int amplitude)
580{
581 int state = 0, count = 0;
582 int interval = NATIVE_FREQUENCY / frequency;
583 int pos;
584 short *buf = (short *)audiobuffer;
585 int bufsize = pcmbuf_size / 2;
586
587 /* FIXME: Should start playback. */
588 //if (pcmbuf_unplayed_bytes * 1000 < 4 * NATIVE_FREQUENCY * duration)
589 // return ;
590
591 pos = (audiobuffer_pos - pcmbuf_unplayed_bytes) / 2;
592 if (pos < 0)
593 pos += bufsize;
594
595 duration = NATIVE_FREQUENCY / 1000 * duration;
596 while (duration-- > 0)
597 {
598 if (state) {
599 buf[pos] = MIN(MAX(buf[pos] + amplitude, -32768), 32767);
600 if (++pos >= bufsize)
601 pos = 0;
602 buf[pos] = MIN(MAX(buf[pos] + amplitude, -32768), 32767);
603 } else {
604 buf[pos] = MIN(MAX(buf[pos] - amplitude, -32768), 32767);
605 if (++pos >= bufsize)
606 pos = 0;
607 buf[pos] = MIN(MAX(buf[pos] - amplitude, -32768), 32767);
608 }
609
610 if (++count >= interval)
611 {
612 count = 0;
613 if (state)
614 state = 0;
615 else
616 state = 1;
617 }
618 pos++;
619 if (pos >= bufsize)
620 pos = 0;
621 }
622}
623
624/* Returns pcm buffer usage in percents (0 to 100). */
625int pcmbuf_usage(void)
626{
627 return pcmbuf_unplayed_bytes * 100 / pcmbuf_size;
628}
629
630int pcmbuf_mix_usage(void)
631{
632 return pcmbuf_mix_used_bytes * 100 / pcmbuf_unplayed_bytes;
633}
634
635void pcmbuf_reset_mixpos(void)
636{
637 int bufsize = pcmbuf_size / 2;
638
639 pcmbuf_mix_used_bytes = 0;
640 mixpos = (audiobuffer_pos - pcmbuf_unplayed_bytes) / 2;
641 if (mixpos < 0)
642 mixpos += bufsize;
643 if (mixpos >= bufsize)
644 mixpos -= bufsize;
645}
646
647void pcmbuf_mix(char *buf, long length)
648{
649 short *ibuf = (short *)buf;
650 short *obuf = (short *)audiobuffer;
651 int bufsize = pcmbuf_size / 2;
652
653 if (pcmbuf_mix_used_bytes == 0)
654 pcmbuf_reset_mixpos();
655
656 pcmbuf_mix_used_bytes += length;
657 length /= 2;
658
659 while (length-- > 0) {
660 obuf[mixpos] = MIN(MAX(obuf[mixpos] + *ibuf*4, -32768), 32767);
661
662 ibuf++;
663 mixpos++;
664 if (mixpos >= bufsize)
665 mixpos = 0;
666 }
667}
668
565void pcmbuf_crossfade_enable(bool on_off) 669void pcmbuf_crossfade_enable(bool on_off)
566{ 670{
567 crossfade_enabled = on_off; 671 crossfade_enabled = on_off;