1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
|
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_TONEGENERATOR_H_
#define ANDROID_TONEGENERATOR_H_
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>
namespace android {
class ToneGenerator {
public:
// List of all available tones
// This enum must be kept consistant with constants in ToneGenerator JAVA class
enum tone_type {
// DTMF tones ITU-T Recommendation Q.23
TONE_DTMF_0 = 0, // 0 key: 1336Hz, 941Hz
TONE_DTMF_1, // 1 key: 1209Hz, 697Hz
TONE_DTMF_2, // 2 key: 1336Hz, 697Hz
TONE_DTMF_3, // 3 key: 1477Hz, 697Hz
TONE_DTMF_4, // 4 key: 1209Hz, 770Hz
TONE_DTMF_5, // 5 key: 1336Hz, 770Hz
TONE_DTMF_6, // 6 key: 1477Hz, 770Hz
TONE_DTMF_7, // 7 key: 1209Hz, 852Hz
TONE_DTMF_8, // 8 key: 1336Hz, 852Hz
TONE_DTMF_9, // 9 key: 1477Hz, 852Hz
TONE_DTMF_S, // * key: 1209Hz, 941Hz
TONE_DTMF_P, // # key: 1477Hz, 941Hz
TONE_DTMF_A, // A key: 1633Hz, 697Hz
TONE_DTMF_B, // B key: 1633Hz, 770Hz
TONE_DTMF_C, // C key: 1633Hz, 852Hz
TONE_DTMF_D, // D key: 1633Hz, 941Hz
// Call supervisory tones: 3GPP TS 22.001 (CEPT)
TONE_SUP_DIAL, // Dial tone: CEPT: 425Hz, continuous
FIRST_SUP_TONE = TONE_SUP_DIAL,
TONE_SUP_BUSY, // Busy tone, CEPT: 425Hz, 500ms ON, 500ms OFF...
TONE_SUP_CONGESTION, // Congestion tone CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF...
TONE_SUP_RADIO_ACK, // Radio path acknowlegment, CEPT, ANSI: 425Hz, 200ms ON
TONE_SUP_RADIO_NOTAVAIL, // Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts
TONE_SUP_ERROR, // Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF...
TONE_SUP_CALL_WAITING, // Call Waiting CEPT,JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
TONE_SUP_RINGTONE, // Ring Tone CEPT, JAPAN: 425Hz, 1s ON, 4s OFF...
LAST_SUP_TONE = TONE_SUP_RINGTONE,
// Proprietary tones: 3GPP TS 31.111
TONE_PROP_BEEP, // General beep: 400Hz+1200Hz, 35ms ON
TONE_PROP_ACK, // Positive Acknowlgement: 1200Hz, 100ms ON, 100ms OFF 2 bursts
TONE_PROP_NACK, // Negative Acknowlgement: 300Hz+400Hz+500Hz, 400ms ON
TONE_PROP_PROMPT, // Prompt tone: 400Hz+1200Hz, 200ms ON
TONE_PROP_BEEP2, // General double beep: 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms on
// Additional call supervisory tones: specified by IS-95 only
TONE_SUP_INTERCEPT, // Intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms.
TONE_SUP_INTERCEPT_ABBREV, // Abbreviated intercept: intercept tone limited to 4 seconds
TONE_SUP_CONGESTION_ABBREV, // Abbreviated congestion: congestion tone limited to 4 seconds
TONE_SUP_CONFIRM, // Confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle.
TONE_SUP_PIP, // Pip tone: four bursts of 480 Hz tone (0.1 s on, 0.1 s off).
// CDMA Tones
TONE_CDMA_DIAL_TONE_LITE,
TONE_CDMA_NETWORK_USA_RINGBACK,
TONE_CDMA_INTERCEPT,
TONE_CDMA_ABBR_INTERCEPT,
TONE_CDMA_REORDER,
TONE_CDMA_ABBR_REORDER,
TONE_CDMA_NETWORK_BUSY,
TONE_CDMA_CONFIRM,
TONE_CDMA_ANSWER,
TONE_CDMA_NETWORK_CALLWAITING,
TONE_CDMA_PIP,
// ISDN
TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL, // ISDN Alert Normal
TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP, // ISDN Intergroup
TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI, // ISDN SP PRI
TONE_CDMA_CALL_SIGNAL_ISDN_PAT3, // ISDN Alert PAT3
TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING, // ISDN Alert PING RING
TONE_CDMA_CALL_SIGNAL_ISDN_PAT5, // ISDN Alert PAT5
TONE_CDMA_CALL_SIGNAL_ISDN_PAT6, // ISDN Alert PAT6
TONE_CDMA_CALL_SIGNAL_ISDN_PAT7, // ISDN Alert PAT7
// ISDN end
// IS54
TONE_CDMA_HIGH_L, // IS54 High Pitch Long
TONE_CDMA_MED_L, // IS54 Med Pitch Long
TONE_CDMA_LOW_L, // IS54 Low Pitch Long
TONE_CDMA_HIGH_SS, // IS54 High Pitch Short Short
TONE_CDMA_MED_SS, // IS54 Medium Pitch Short Short
TONE_CDMA_LOW_SS, // IS54 Low Pitch Short Short
TONE_CDMA_HIGH_SSL, // IS54 High Pitch Short Short Long
TONE_CDMA_MED_SSL, // IS54 Medium Pitch Short Short Long
TONE_CDMA_LOW_SSL, // IS54 Low Pitch Short Short Long
TONE_CDMA_HIGH_SS_2, // IS54 High Pitch Short Short 2
TONE_CDMA_MED_SS_2, // IS54 Med Pitch Short Short 2
TONE_CDMA_LOW_SS_2, // IS54 Low Pitch Short Short 2
TONE_CDMA_HIGH_SLS, // IS54 High Pitch Short Long Short
TONE_CDMA_MED_SLS, // IS54 Med Pitch Short Long Short
TONE_CDMA_LOW_SLS, // IS54 Low Pitch Short Long Short
TONE_CDMA_HIGH_S_X4, // IS54 High Pitch Short Short Short Short
TONE_CDMA_MED_S_X4, // IS54 Med Pitch Short Short Short Short
TONE_CDMA_LOW_S_X4, // IS54 Low Pitch Short Short Short Short
TONE_CDMA_HIGH_PBX_L, // PBX High Pitch Long
TONE_CDMA_MED_PBX_L, // PBX Med Pitch Long
TONE_CDMA_LOW_PBX_L, // PBX Low Pitch Long
TONE_CDMA_HIGH_PBX_SS, // PBX High Short Short
TONE_CDMA_MED_PBX_SS, // PBX Med Short Short
TONE_CDMA_LOW_PBX_SS, // PBX Low Short Short
TONE_CDMA_HIGH_PBX_SSL, // PBX High Short Short Long
TONE_CDMA_MED_PBX_SSL, // PBX Med Short Short Long
TONE_CDMA_LOW_PBX_SSL, // PBX Low Short Short Long
TONE_CDMA_HIGH_PBX_SLS, // PBX High SLS
TONE_CDMA_MED_PBX_SLS, // PBX Med SLS
TONE_CDMA_LOW_PBX_SLS, // PBX Low SLS
TONE_CDMA_HIGH_PBX_S_X4, // PBX High SSSS
TONE_CDMA_MED_PBX_S_X4, // PBX Med SSSS
TONE_CDMA_LOW_PBX_S_X4, // PBX LOW SSSS
//IS54 end
// proprietary
TONE_CDMA_ALERT_NETWORK_LITE,
TONE_CDMA_ALERT_AUTOREDIAL_LITE,
TONE_CDMA_ONE_MIN_BEEP,
TONE_CDMA_KEYPAD_VOLUME_KEY_LITE,
TONE_CDMA_PRESSHOLDKEY_LITE,
TONE_CDMA_ALERT_INCALL_LITE,
TONE_CDMA_EMERGENCY_RINGBACK,
TONE_CDMA_ALERT_CALL_GUARD,
TONE_CDMA_SOFT_ERROR_LITE,
TONE_CDMA_CALLDROP_LITE,
// proprietary end
TONE_CDMA_NETWORK_BUSY_ONE_SHOT,
TONE_CDMA_ABBR_ALERT,
TONE_CDMA_SIGNAL_OFF,
//CDMA end
NUM_TONES,
NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
};
ToneGenerator(int streamType, float volume);
~ToneGenerator();
bool startTone(int toneType);
void stopTone();
bool isInited() { return (mState == TONE_IDLE)?false:true;}
private:
enum tone_state {
TONE_IDLE, // ToneGenerator is being initialized or initialization failed
TONE_INIT, // ToneGenerator has been successfully initialized and is not playing
TONE_STARTING, // ToneGenerator is starting playing
TONE_PLAYING, // ToneGenerator is playing
TONE_STOPPING, // ToneGenerator is stoping
TONE_RESTARTING //
};
// Region specific tones.
// These supervisory tones are different depending on the region (USA/CANADA, JAPAN, rest of the world).
// When a tone in the range [FIRST_SUP_TONE, LAST_SUP_TONE] is requested, the region is determined
// from system property gsm.operator.iso-country and the proper tone descriptor is selected with the
// help of sToneMappingTable[]
enum regional_tone_type {
// ANSI supervisory tones
TONE_ANSI_DIAL = NUM_TONES, // Dial tone: a continuous 350 Hz + 440 Hz tone.
TONE_ANSI_BUSY, // Busy tone on: a 480 Hz + 620 Hz tone repeated in a 500 ms on, 500 ms off cycle.
TONE_ANSI_CONGESTION, // Network congestion (reorder) tone on: a 480 Hz + 620 Hz tone repeated in a 250 ms on, 250 ms off cycle.
TONE_ANSI_CALL_WAITING, // Call waiting tone on: 440 Hz, on for 300 ms, 9,7 s off followed by
// (440 Hz, on for 100 ms off for 100 ms, on for 100 ms, 9,7s off and repeated as necessary).
TONE_ANSI_RINGTONE, // Ring Tone: a 440 Hz + 480 Hz tone repeated in a 2 s on, 4 s off pattern.
// JAPAN Supervisory tones
TONE_JAPAN_DIAL, // Dial tone: 400Hz, continuous
TONE_JAPAN_BUSY, // Busy tone: 400Hz, 500ms ON, 500ms OFF...
TONE_JAPAN_RADIO_ACK, // Radio path acknowlegment: 400Hz, 1s ON, 2s OFF...
NUM_ALTERNATE_TONES
};
enum region {
ANSI,
JAPAN,
CEPT,
NUM_REGIONS
};
static const unsigned char sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES];
static const unsigned int TONEGEN_MAX_WAVES = 3; // Maximun number of sine waves in a tone segment
static const unsigned int TONEGEN_MAX_SEGMENTS = 12; // Maximun number of segments in a tone descriptor
static const unsigned int TONEGEN_INF = 0xFFFFFFFF; // Represents infinite time duration
static const float TONEGEN_GAIN = 0.9; // Default gain passed to WaveGenerator().
// ToneDescriptor class contains all parameters needed to generate a tone:
// - The array waveFreq[]:
// 1 for static tone descriptors: contains the frequencies of all individual waves making the multi-tone.
// 2 for active tone descritors: contains the indexes of the WaveGenerator objects in mWaveGens
// The number of sine waves varies from 1 to TONEGEN_MAX_WAVES.
// The first null value indicates that no more waves are needed.
// - The array segments[] is used to generate the tone pulses. A segment is a period of time
// during which the tone is ON or OFF. Segments with even index (starting from 0)
// correspond to tone ON state and segments with odd index to OFF state.
// The data stored in segments[] is the duration of the corresponding period in ms.
// The first segment encountered with a 0 duration indicates that no more segment follows.
// - loopCnt - Number of times to repeat a sequence of seqments after playing this
// - loopIndx - The segment index to go back and play is loopcnt > 0
// - repeatCnt indicates the number of times the sequence described by segments[] array must be repeated.
// When the tone generator encounters the first 0 duration segment, it will compare repeatCnt to mCurCount.
// If mCurCount > repeatCnt, the tone is stopped automatically. Otherwise, tone sequence will be
// restarted from segment repeatSegment.
// - repeatSegment number of the first repeated segment when repeatCnt is not null
class ToneSegment {
public:
unsigned int duration;
unsigned short waveFreq[TONEGEN_MAX_WAVES+1];
unsigned short loopCnt;
unsigned short loopIndx;
};
class ToneDescriptor {
public:
ToneSegment segments[TONEGEN_MAX_SEGMENTS+1];
unsigned long repeatCnt;
unsigned long repeatSegment;
};
static const ToneDescriptor sToneDescriptors[];
unsigned int mTotalSmp; // Total number of audio samples played (gives current time)
unsigned int mNextSegSmp; // Position of next segment transition expressed in samples
// NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly
// only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded,
// no crash will occur but tone sequence will show a glitch.
unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[]
unsigned short mCurCount; // Current sequence repeat count
volatile unsigned short mState; // ToneGenerator state (tone_state)
unsigned short mRegion;
const ToneDescriptor *mpToneDesc; // pointer to active tone descriptor
const ToneDescriptor *mpNewToneDesc; // pointer to next active tone descriptor
unsigned short mLoopCounter; // Current tone loopback count
int mSamplingRate; // AudioFlinger Sampling rate
AudioTrack *mpAudioTrack; // Pointer to audio track used for playback
Mutex mLock; // Mutex to control concurent access to ToneGenerator object from audio callback and application API
Mutex mCbkCondLock; // Mutex associated to mWaitCbkCond
Condition mWaitCbkCond; // condition enabling interface to wait for audio callback completion after a change is requested
float mVolume; // Volume applied to audio track
int mStreamType; // Audio stream used for output
unsigned int mProcessSize; // Size of audio blocks generated at a time by audioCallback() (in PCM frames).
bool initAudioTrack();
static void audioCallback(int event, void* user, void *info);
bool prepareWave();
unsigned int numWaves(unsigned int segmentIdx);
void clearWaveGens();
int getToneForRegion(int toneType);
// WaveGenerator generates a single sine wave
class WaveGenerator {
public:
enum gen_command {
WAVEGEN_START, // Start/restart wave from phase 0
WAVEGEN_CONT, // Continue wave from current phase
WAVEGEN_STOP // Stop wave on zero crossing
};
WaveGenerator(unsigned short samplingRate, unsigned short frequency,
float volume);
~WaveGenerator();
void getSamples(short *outBuffer, unsigned int count,
unsigned int command);
private:
static const short GEN_AMP = 32000; // amplitude of generator
static const short S_Q14 = 14; // shift for Q14
static const short S_Q15 = 15; // shift for Q15
short mA1_Q14; // Q14 coefficient
// delay line of full amplitude generator
short mS1, mS2; // delay line S2 oldest
short mS2_0; // saved value for reinitialisation
short mAmplitude_Q15; // Q15 amplitude
};
KeyedVector<unsigned short, WaveGenerator *> mWaveGens; // list of active wave generators.
};
}
; // namespace android
#endif /*ANDROID_TONEGENERATOR_H_*/
|