summaryrefslogtreecommitdiff
path: root/apps/beep.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-06-29 06:37:04 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-06-29 06:37:04 +0000
commita2b6703a369f6cdbfec1f150c408dadc877631fb (patch)
tree3145a8c1372c44711d38feefeba39c7d4098f139 /apps/beep.c
parent8411614b8a068a4f274c3841aa55aab1df1bc246 (diff)
downloadrockbox-a2b6703a369f6cdbfec1f150c408dadc877631fb.tar.gz
rockbox-a2b6703a369f6cdbfec1f150c408dadc877631fb.zip
Commit FS#12150 - Fully-functional audio mixer - and finally whip old limitations about playback of voice and other sounds when paused. Channels are independent in state and amplitude. Fade on stop/pause is handled by the channel's volume control rather than global volume which means it now works from anywhere. Opens up the possibility of plugin sounds during music playback by merely adding an additional channel enum. If any PCM drivers were not properly modified, see one of the last comments in the task for a description of the simple change that is expected. Some params are tunable in firmware/export/pcm-mixer.h as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30097 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/beep.c')
-rw-r--r--apps/beep.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/apps/beep.c b/apps/beep.c
new file mode 100644
index 0000000000..716847263e
--- /dev/null
+++ b/apps/beep.c
@@ -0,0 +1,142 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (c) 2011 Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "system.h"
23#include "settings.h"
24#include "dsp.h"
25#include "pcm.h"
26#include "pcm_mixer.h"
27#include "misc.h"
28
29static int32_t beep_phase; /* Phase of square wave generator */
30static uint32_t beep_step; /* Step of square wave generator on each sample */
31static uint32_t beep_amplitude; /* Amplitude of square wave generator */
32static int beep_count; /* Number of samples remaining to generate */
33
34/* Reserve enough static space for keyclick to fit */
35#define BEEP_BUF_COUNT (NATIVE_FREQUENCY / 1000 * KEYCLICK_DURATION)
36static uint32_t beep_buf[BEEP_BUF_COUNT] IBSS_ATTR;
37
38/* Actually output samples into beep_buf */
39#if defined(CPU_ARM)
40static FORCE_INLINE void beep_generate(int count)
41{
42 uint32_t *out = beep_buf;
43 uint32_t s;
44
45 asm volatile (
46 "1: \n"
47 "eor %3, %5, %1, asr #31 \n"
48 "subs %2, %2, #1 \n"
49 "str %3, [%0], #4 \n"
50 "add %1, %1, %4 \n"
51 "bgt 1b \n"
52 : "+r"(out), "+r"(beep_phase), "+r"(count),
53 "=&r"(s)
54 : "r"(beep_step), "r"(beep_amplitude));
55}
56#elif defined (CPU_COLDFIRE)
57static FORCE_INLINE void beep_generate(int count)
58{
59 uint32_t *out = beep_buf;
60 uint32_t s;
61
62 asm volatile (
63 "1: \n"
64 "move.l %1, %3 \n"
65 "add.l %4, %1 \n"
66 "add.l %3, %3 \n"
67 "subx.l %3, %3 \n"
68 "eor.l %5, %3 \n"
69 "move.l %3, (%0)+ \n"
70 "subq.l #1, %2 \n"
71 "bgt.b 1b \n"
72 : "+a"(out), "+d"(beep_phase), "+d"(count),
73 "=&d"(s)
74 : "r"(beep_step), "d"(beep_amplitude));
75}
76#else
77static FORCE_INLINE void beep_generate(int count)
78{
79 uint32_t *out = beep_buf;
80 uint32_t amplitude = beep_amplitude;
81 uint32_t step = beep_step;
82 int32_t phase = beep_phase;
83
84 do
85 {
86 *out++ = (phase >> 31) ^ amplitude;
87 phase += step;
88 }
89 while (--count > 0);
90
91 beep_phase = phase;
92}
93#endif
94
95/* Callback to generate the beep frames - also don't want inlining of
96 call below in beep_play */
97static void __attribute__((noinline)) ICODE_ATTR
98beep_get_more(unsigned char **start, size_t *size)
99{
100 int count = beep_count;
101
102 if (count > 0)
103 {
104 count = MIN(count, BEEP_BUF_COUNT);
105 beep_count -= count;
106 *start = (unsigned char *)beep_buf;
107 *size = count * sizeof(uint32_t);
108 beep_generate(count);
109 }
110}
111
112/* Generates a constant square wave sound with a given frequency in Hertz for
113 a duration in milliseconds */
114void beep_play(unsigned int frequency, unsigned int duration,
115 unsigned int amplitude)
116{
117 mixer_channel_stop(PCM_MIXER_CHAN_BEEP);
118
119 if (frequency == 0 || duration == 0 || amplitude == 0)
120 return;
121
122 if (amplitude > INT16_MAX)
123 amplitude = INT16_MAX;
124
125 /* Setup the parameters for the square wave generator */
126 beep_phase = 0;
127 beep_step = 0xffffffffu / NATIVE_FREQUENCY * frequency;
128 beep_count = NATIVE_FREQUENCY / 1000 * duration;
129 beep_amplitude = amplitude | (amplitude << 16); /* Word:|AMP16|AMP16| */
130
131 /* If it fits - avoid cb overhead */
132 unsigned char *start;
133 size_t size;
134
135 /* Generate first frame here */
136 beep_get_more(&start, &size);
137
138 mixer_channel_set_amplitude(PCM_MIXER_CHAN_BEEP, MIX_AMP_UNITY);
139 mixer_channel_play_data(PCM_MIXER_CHAN_BEEP,
140 beep_count ? beep_get_more : NULL,
141 start, size);
142}