blob: 9f1b3d67edf92f6d51d7874e5bd1dbb6f8ef8452 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "ToneGenerator"
19#include <utils/threads.h>
20
21#include <stdio.h>
22#include <math.h>
23#include <utils/Log.h>
24#include <sys/resource.h>
25#include <utils/RefBase.h>
26#include <utils/Timers.h>
Eric Laurentf3af7402009-05-05 00:49:01 -070027#include <cutils/properties.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028#include "media/ToneGenerator.h"
29
Eric Laurentf3af7402009-05-05 00:49:01 -070030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031namespace android {
32
Eric Laurentf3af7402009-05-05 00:49:01 -070033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034// Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details)
Eric Laurentf3af7402009-05-05 00:49:01 -070035const ToneGenerator::ToneDescriptor ToneGenerator::sToneDescriptors[] = {
David Krauseb6d90ca2009-06-17 15:46:13 -050036 { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 941, 0 }, 0, 0},
37 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070038 repeatCnt: ToneGenerator::TONEGEN_INF,
39 repeatSegment: 0 }, // TONE_DTMF_0
David Krauseb6d90ca2009-06-17 15:46:13 -050040 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 697, 0 }, 0, 0 },
41 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070042 repeatCnt: ToneGenerator::TONEGEN_INF,
43 repeatSegment: 0 }, // TONE_DTMF_1
David Krauseb6d90ca2009-06-17 15:46:13 -050044 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 697, 0 }, 0, 0 },
45 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070046 repeatCnt: ToneGenerator::TONEGEN_INF,
47 repeatSegment: 0 }, // TONE_DTMF_2
David Krauseb6d90ca2009-06-17 15:46:13 -050048 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 697, 0 }, 0, 0 },
49 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070050 repeatCnt: ToneGenerator::TONEGEN_INF,
51 repeatSegment: 0 }, // TONE_DTMF_3
David Krauseb6d90ca2009-06-17 15:46:13 -050052 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 770, 0 }, 0, 0 },
53 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070054 repeatCnt: ToneGenerator::TONEGEN_INF,
55 repeatSegment: 0 }, // TONE_DTMF_4
David Krauseb6d90ca2009-06-17 15:46:13 -050056 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 770, 0 }, 0, 0 },
57 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070058 repeatCnt: ToneGenerator::TONEGEN_INF,
59 repeatSegment: 0 }, // TONE_DTMF_5
David Krauseb6d90ca2009-06-17 15:46:13 -050060 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 770, 0 }, 0, 0 },
61 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070062 repeatCnt: ToneGenerator::TONEGEN_INF,
63 repeatSegment: 0 }, // TONE_DTMF_6
David Krauseb6d90ca2009-06-17 15:46:13 -050064 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 852, 0 }, 0, 0 },
65 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070066 repeatCnt: ToneGenerator::TONEGEN_INF,
67 repeatSegment: 0 }, // TONE_DTMF_7
David Krauseb6d90ca2009-06-17 15:46:13 -050068 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 852, 0 }, 0, 0 },
69 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070070 repeatCnt: ToneGenerator::TONEGEN_INF,
71 repeatSegment: 0 }, // TONE_DTMF_8
David Krauseb6d90ca2009-06-17 15:46:13 -050072 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 852, 0 }, 0, 0 },
73 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070074 repeatCnt: ToneGenerator::TONEGEN_INF,
75 repeatSegment: 0 }, // TONE_DTMF_9
David Krauseb6d90ca2009-06-17 15:46:13 -050076 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 941, 0 }, 0, 0 },
77 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070078 repeatCnt: ToneGenerator::TONEGEN_INF,
79 repeatSegment: 0 }, // TONE_DTMF_S
David Krauseb6d90ca2009-06-17 15:46:13 -050080 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 941, 0 }, 0, 0 },
81 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070082 repeatCnt: ToneGenerator::TONEGEN_INF,
83 repeatSegment: 0 }, // TONE_DTMF_P
David Krauseb6d90ca2009-06-17 15:46:13 -050084 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 697, 0 }, 0, 0 },
85 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070086 repeatCnt: ToneGenerator::TONEGEN_INF,
87 repeatSegment: 0 }, // TONE_DTMF_A
David Krauseb6d90ca2009-06-17 15:46:13 -050088 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 770, 0 }, 0, 0 },
89 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070090 repeatCnt: ToneGenerator::TONEGEN_INF,
91 repeatSegment: 0 }, // TONE_DTMF_B
David Krauseb6d90ca2009-06-17 15:46:13 -050092 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 852, 0 }, 0, 0 },
93 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070094 repeatCnt: ToneGenerator::TONEGEN_INF,
95 repeatSegment: 0 }, // TONE_DTMF_C
David Krauseb6d90ca2009-06-17 15:46:13 -050096 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 941, 0 }, 0, 0 },
97 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -070098 repeatCnt: ToneGenerator::TONEGEN_INF,
99 repeatSegment: 0 }, // TONE_DTMF_D
David Krauseb6d90ca2009-06-17 15:46:13 -0500100 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0 },
101 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700102 repeatCnt: ToneGenerator::TONEGEN_INF,
103 repeatSegment: 0 }, // TONE_SUP_DIAL
David Krauseb6d90ca2009-06-17 15:46:13 -0500104 { segments: { { duration: 500 , waveFreq: { 425, 0 }, 0, 0},
105 { duration: 500, waveFreq: { 0 }, 0, 0},
106 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700107 repeatCnt: ToneGenerator::TONEGEN_INF,
108 repeatSegment: 0 }, // TONE_SUP_BUSY
David Krauseb6d90ca2009-06-17 15:46:13 -0500109 { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
110 { duration: 200, waveFreq: { 0 }, 0, 0 },
111 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700112 repeatCnt: ToneGenerator::TONEGEN_INF,
113 repeatSegment: 0 }, // TONE_SUP_CONGESTION
David Krauseb6d90ca2009-06-17 15:46:13 -0500114 { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
115 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700116 repeatCnt: 0,
117 repeatSegment: 0 }, // TONE_SUP_RADIO_ACK
David Krauseb6d90ca2009-06-17 15:46:13 -0500118 { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0},
119 { duration: 200, waveFreq: { 0 }, 0, 0},
120 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700121 repeatCnt: 2,
122 repeatSegment: 0 }, // TONE_SUP_RADIO_NOTAVAIL
David Krauseb6d90ca2009-06-17 15:46:13 -0500123 { segments: { { duration: 330, waveFreq: { 950, 1400, 1800, 0 }, 0, 0},
124 { duration: 1000, waveFreq: { 0 }, 0, 0},
125 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700126 repeatCnt: ToneGenerator::TONEGEN_INF,
127 repeatSegment: 0 }, // TONE_SUP_ERROR
David Krauseb6d90ca2009-06-17 15:46:13 -0500128 { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
129 { duration: 600, waveFreq: { 0 }, 0, 0 },
130 { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
131 { duration: 3000, waveFreq: { 0 }, 0, 0 },
132 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700133 repeatCnt: ToneGenerator::TONEGEN_INF,
134 repeatSegment: 0 }, // TONE_SUP_CALL_WAITING
David Krauseb6d90ca2009-06-17 15:46:13 -0500135 { segments: { { duration: 1000, waveFreq: { 425, 0 }, 0, 0 },
136 { duration: 4000, waveFreq: { 0 }, 0, 0 },
137 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700138 repeatCnt: ToneGenerator::TONEGEN_INF,
139 repeatSegment: 0 }, // TONE_SUP_RINGTONE
David Krauseb6d90ca2009-06-17 15:46:13 -0500140 { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
141 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700142 repeatCnt: 0,
143 repeatSegment: 0 }, // TONE_PROP_BEEP
David Krauseb6d90ca2009-06-17 15:46:13 -0500144 { segments: { { duration: 100, waveFreq: { 1200, 0 }, 0, 0 },
145 { duration: 100, waveFreq: { 0 }, 0, 0 },
146 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700147 repeatCnt: 1,
148 repeatSegment: 0 }, // TONE_PROP_ACK
David Krauseb6d90ca2009-06-17 15:46:13 -0500149 { segments: { { duration: 400, waveFreq: { 300, 400, 500, 0 }, 0, 0 },
150 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700151 repeatCnt: 0,
152 repeatSegment: 0 }, // TONE_PROP_NACK
David Krauseb6d90ca2009-06-17 15:46:13 -0500153 { segments: { { duration: 200, waveFreq: { 400, 1200, 0 }, 0, 0 },
154 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700155 repeatCnt: 0,
156 repeatSegment: 0 }, // TONE_PROP_PROMPT
David Krauseb6d90ca2009-06-17 15:46:13 -0500157 { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
158 { duration: 200, waveFreq: { 0 }, 0, 0 },
159 { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
160 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700161 repeatCnt: 0,
162 repeatSegment: 0 }, // TONE_PROP_BEEP2
David Krauseb6d90ca2009-06-17 15:46:13 -0500163 { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
164 { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
165 { duration: 0 , waveFreq: { 0 }, 0, 0 }},
Eric Laurentf3af7402009-05-05 00:49:01 -0700166 repeatCnt: ToneGenerator::TONEGEN_INF,
167 repeatSegment: 0 }, // TONE_SUP_INTERCEPT
David Krauseb6d90ca2009-06-17 15:46:13 -0500168 { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
169 { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
170 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700171 repeatCnt: 7,
172 repeatSegment: 0 }, // TONE_SUP_INTERCEPT_ABBREV
David Krauseb6d90ca2009-06-17 15:46:13 -0500173 { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
174 { duration: 250, waveFreq: { 0 }, 0, 0 },
175 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700176 repeatCnt: 7,
177 repeatSegment: 0 }, // TONE_SUP_CONGESTION_ABBREV
David Krauseb6d90ca2009-06-17 15:46:13 -0500178 { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
179 { duration: 100, waveFreq: { 0 }, 0, 0 },
180 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700181 repeatCnt: 2,
182 repeatSegment: 0 }, // TONE_SUP_CONFIRM
David Krauseb6d90ca2009-06-17 15:46:13 -0500183 { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
184 { duration: 100, waveFreq: { 0 }, 0, 0 },
185 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700186 repeatCnt: 3,
187 repeatSegment: 0 }, // TONE_SUP_PIP
David Krauseb6d90ca2009-06-17 15:46:13 -0500188 { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0},
189 { duration: 0 , waveFreq: { 0 }, 0, 0}},
190 repeatCnt: ToneGenerator::TONEGEN_INF,
191 repeatSegment: 0 }, // TONE_CDMA_DIAL_TONE_LITE
192 { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
193 { duration: 4000, waveFreq: { 0 }, 0, 0 },
194 { duration: 0 , waveFreq: { 0 }, 0, 0}},
195 repeatCnt: ToneGenerator::TONEGEN_INF,
196 repeatSegment: 0 }, // TONE_CDMA_NETWORK_USA_RINGBACK
197 { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
198 { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
199 { duration: 0 , waveFreq: { 0 }, 0, 0}},
200 repeatCnt: ToneGenerator::TONEGEN_INF,
201 repeatSegment: 0 }, // TONE_CDMA_INTERCEPT
202 { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
203 { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
204 { duration: 0 , waveFreq: { 0 }, 0, 0}},
205 repeatCnt: 0,
206 repeatSegment: 0 }, // TONE_CDMA_ABBR_INTERCEPT
207 { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
208 { duration: 250, waveFreq: { 0 }, 0, 0 },
209 { duration: 0 , waveFreq: { 0 }, 0, 0}},
210 repeatCnt: ToneGenerator::TONEGEN_INF,
211 repeatSegment: 0 }, // TONE_CDMA_REORDER
212 { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
213 { duration: 250, waveFreq: { 0 }, 0, 0 },
214 { duration: 0 , waveFreq: { 0 }, 0, 0}},
215 repeatCnt: 7,
216 repeatSegment: 0 }, // TONE_CDMA_ABBR_REORDER
217 { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
218 { duration: 500, waveFreq: { 0 }, 0, 0 },
219 { duration: 0 , waveFreq: { 0 }, 0, 0}},
220 repeatCnt: ToneGenerator::TONEGEN_INF,
221 repeatSegment: 0 }, // TONE_CDMA_NETWORK_BUSY
222 { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
223 { duration: 100, waveFreq: { 0 }, 0, 0 },
224 { duration: 0 , waveFreq: { 0 }, 0, 0}},
225 repeatCnt: 2,
226 repeatSegment: 0 }, // TONE_CDMA_CONFIRM
Naveen Kalla6c84d732009-10-13 15:29:47 -0700227 { segments: { { duration: 500, waveFreq: { 660, 1000, 0 }, 0, 0 },
228 { duration: 0 , waveFreq: { 0 }, 0, 0}},
David Krauseb6d90ca2009-06-17 15:46:13 -0500229 repeatCnt: 0,
230 repeatSegment: 0 }, // TONE_CDMA_ANSWER
231 { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
232 { duration: 0 , waveFreq: { 0 }, 0, 0}},
233 repeatCnt: 0,
234 repeatSegment: 0 }, // TONE_CDMA_NETWORK_CALLWAITING
235 { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
236 { duration: 100, waveFreq: { 0 }, 0, 0 },
237 { duration: 0 , waveFreq: { 0 }, 0, 0}},
238 repeatCnt: 3,
239 repeatSegment: 0 }, // TONE_CDMA_PIP
240
241 { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
242 { duration: 64, waveFreq: { 2556, 0}, 19, 0},
243 { duration: 32, waveFreq: { 2091, 0}, 0, 0},
244 { duration: 48, waveFreq: { 2556, 0}, 0, 0},
245 { duration: 4000, waveFreq: { 0 }, 0, 0},
246 { duration: 0, waveFreq: { 0 }, 0, 0}},
247 repeatCnt: 0,
248 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL
249 { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
250 { duration: 64, waveFreq: { 2556, 0}, 7, 0 },
251 { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
252 { duration: 400, waveFreq: { 0 }, 0, 0 },
253 { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
254 { duration: 64, waveFreq: { 2556, 0}, 7, 4 },
255 { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
256 { duration: 4000, waveFreq: { 0 }, 0, 0 },
257 { duration: 0, waveFreq: { 0 }, 0, 0 } },
258 repeatCnt: 0,
259 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP
260 { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
261 { duration: 64, waveFreq: { 2556, 0}, 3, 0 },
262 { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
263 { duration: 200, waveFreq: { 0 }, 0, 0 },
264 { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
265 { duration: 64, waveFreq: { 2556, 0}, 3, 4 },
266 { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
267 { duration: 200, waveFreq: { 0 }, 0, 0 },
268 { duration: 0, waveFreq: { 0 }, 0, 0 } },
269 repeatCnt: 0,
270 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI
271 { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
272 repeatCnt: 0,
273 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT3
274 { segments: { { duration: 32, waveFreq: { 2091, 0 }, 0, 0 },
275 { duration: 64, waveFreq: { 2556, 0 }, 4, 0 },
276 { duration: 20, waveFreq: { 2091, 0 }, 0, 0 },
277 { duration: 0, waveFreq: { 0 } , 0, 0 } },
278 repeatCnt: 0,
279 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING
280 { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
281 repeatCnt: 0,
282 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT5
283 { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
284 repeatCnt: 0,
285 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT6
286 { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
287 repeatCnt: 0,
288 repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT7
289
290 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
291 { duration: 25, waveFreq: { 4000, 0 }, 39, 0 },
292 { duration: 4000, waveFreq: { 0 }, 0, 0 },
293 { duration: 0, waveFreq: { 0 }, 0, 0 } },
294 repeatCnt: ToneGenerator::TONEGEN_INF,
295 repeatSegment: 0 }, // TONE_CDMA_HIGH_L
296 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
297 { duration: 25, waveFreq: { 2900, 0 }, 39, 0 },
298 { duration: 4000, waveFreq: { 0 }, 0, 0 },
299 { duration: 0, waveFreq: { 0 }, 0, 0 } },
300 repeatCnt: ToneGenerator::TONEGEN_INF,
301 repeatSegment: 0 }, // TONE_CDMA_MED_L
302 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
303 { duration: 25, waveFreq: { 1450, 0 }, 39, 0 },
304 { duration: 4000, waveFreq: { 0 }, 0, 0 },
305 { duration: 0, waveFreq: { 0 }, 0, 0 } },
306 repeatCnt: ToneGenerator::TONEGEN_INF,
307 repeatSegment: 0 }, // TONE_CDMA_LOW_L
308 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
309 { duration: 25, waveFreq: { 4000, 0 }, 15, 0 },
310 { duration: 400, waveFreq: { 0 }, 0, 0 },
311 { duration: 0, waveFreq: { 0 }, 0, 0 } },
312 repeatCnt: ToneGenerator::TONEGEN_INF,
313 repeatSegment: 0 }, // TONE_CDMA_HIGH_SS
314 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
315 { duration: 25, waveFreq: { 2900, 0 }, 15, 0 },
316 { duration: 400, waveFreq: { 0 }, 0, 0 },
317 { duration: 0, waveFreq: { 0 }, 0, 0 }},
318 repeatCnt: ToneGenerator::TONEGEN_INF,
319 repeatSegment: 0 }, // TONE_CDMA_MED_SS
320 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
321 { duration: 25, waveFreq: { 1450, 0 }, 15, 0 },
322 { duration: 400, waveFreq: { 0 }, 0, 0 },
323 { duration: 0, waveFreq: { 0 }, 0, 0 }},
324 repeatCnt: ToneGenerator::TONEGEN_INF,
325 repeatSegment: 0 }, // TONE_CDMA_LOW_SS
326 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
327 { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
328 { duration: 200, waveFreq: { 0 }, 0, 0 },
329 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
330 { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
331 { duration: 200, waveFreq: { 0 }, 0, 0 },
332 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
333 { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
334 { duration: 4000, waveFreq: { 0 }, 0, 0 },
335 { duration: 0, waveFreq: { 0 }, 0, 0 }},
336 repeatCnt: ToneGenerator::TONEGEN_INF,
337 repeatSegment: 0 }, // TONE_CDMA_HIGH_SSL
338 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
339 { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
340 { duration: 200, waveFreq: { 0 }, 0, 0 },
341 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
342 { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
343 { duration: 200, waveFreq: { 0 }, 0, 0 },
344 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
345 { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
346 { duration: 4000, waveFreq: { 0 }, 0, 0 },
347 { duration: 0, waveFreq: { 0 }, 0, 0 }},
348 repeatCnt: ToneGenerator::TONEGEN_INF,
349 repeatSegment: 0 }, // TONE_CDMA_MED_SSL
350 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
351 { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
352 { duration: 200, waveFreq: { 0 }, 0, 0 },
353 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
354 { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
355 { duration: 200, waveFreq: { 0 }, 0, 0 },
356 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
357 { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
358 { duration: 4000, waveFreq: { 0 }, 0, 0 },
359 { duration: 0, waveFreq: { 0 }, 0, 0 }},
360 repeatCnt: ToneGenerator::TONEGEN_INF,
361 repeatSegment: 0 }, // TONE_CDMA_LOW_SSL
362 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
363 { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
364 { duration: 1000, waveFreq: { 0 }, 0, 0 },
365 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
366 { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
367 { duration: 3000, waveFreq: { 0 }, 0, 0 },
368 { duration: 0, waveFreq: { 0 }, 0, 0 }},
369 repeatCnt: ToneGenerator::TONEGEN_INF,
370 repeatSegment: 0 }, // TONE_CDMA_HIGH_SS_2
371 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
372 { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
373 { duration: 1000, waveFreq: { 0 }, 0, 0 },
374 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
375 { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
376 { duration: 3000, waveFreq: { 0 }, 0, 0 },
377 { duration: 0, waveFreq: { 0 }, 0, 0 }},
378 repeatCnt: ToneGenerator::TONEGEN_INF,
379 repeatSegment: 0 }, // TONE_CDMA_MED_SS_2
380 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
381 { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
382 { duration: 1000, waveFreq: { 0 }, 0, 0 },
383 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
384 { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
385 { duration: 3000, waveFreq: { 0 }, 0, 0 },
386 { duration: 0, waveFreq: { 0 }, 0, 0 }},
387 repeatCnt: ToneGenerator::TONEGEN_INF,
388 repeatSegment: 0 }, // TONE_CDMA_LOW_SS_2
389 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
390 { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
391 { duration: 500, waveFreq: { 0 }, 0, 0 },
392 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
393 { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
394 { duration: 500, waveFreq: { 0 }, 0, 0 },
395 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
396 { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
397 { duration: 3000, waveFreq: { 0 }, 0, 0 },
398 { duration: 0, waveFreq: { 0 }, 0, 0 }},
399 repeatCnt: ToneGenerator::TONEGEN_INF,
400 repeatSegment: 0 }, // TONE_CDMA_HIGH_SLS
401 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
402 { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
403 { duration: 500, waveFreq: { 0 }, 0, 0 },
404 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
405 { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
406 { duration: 500, waveFreq: { 0 }, 0, 0 },
407 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
408 { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
409 { duration: 3000, waveFreq: { 0 }, 0, 0 },
410 { duration: 0, waveFreq: { 0 }, 0, 0 }},
411 repeatCnt: ToneGenerator::TONEGEN_INF,
412 repeatSegment: 0 }, // TONE_CDMA_MED_SLS
413 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
414 { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
415 { duration: 500, waveFreq: { 0 }, 0, 0 },
416 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
417 { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
418 { duration: 500, waveFreq: { 0 }, 0, 0 },
419 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
420 { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
421 { duration: 3000, waveFreq: { 0 }, 0, 0 },
422 { duration: 0, waveFreq: { 0 }, 0, 0 }},
423 repeatCnt: ToneGenerator::TONEGEN_INF,
424 repeatSegment: 0 }, // TONE_CDMA_LOW_SLS
425 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
426 { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
427 { duration: 500, waveFreq: { 0 }, 0, 0 },
428 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
429 { duration: 25, waveFreq: { 4000, 0 }, 9, 3 },
430 { duration: 500, waveFreq: { 0 }, 0, 0 },
431 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
432 { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
433 { duration: 500, waveFreq: { 0 }, 0, 0 },
434 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
435 { duration: 25, waveFreq: { 4000, 0 }, 9, 9 },
436 { duration: 2500, waveFreq: { 0 }, 0, 0 },
437 { duration: 0, waveFreq: { 0 }, 0, 0 }},
438 repeatCnt: ToneGenerator::TONEGEN_INF,
439 repeatSegment: 0 }, // TONE_CDMA_HIGH_S_X4
440 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
441 { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
442 { duration: 500, waveFreq: { 0 }, 0, 0 },
443 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
444 { duration: 25, waveFreq: { 2900, 0 }, 9, 3 },
445 { duration: 500, waveFreq: { 0 }, 0, 0 },
446 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
447 { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
448 { duration: 500, waveFreq: { 0 }, 0, 0 },
449 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
450 { duration: 25, waveFreq: { 2900, 0 }, 9, 9 },
451 { duration: 2500, waveFreq: { 0 }, 0, 0 },
452 { duration: 0, waveFreq: { 0 }, 0, 0 }},
453 repeatCnt: ToneGenerator::TONEGEN_INF,
454 repeatSegment: 0 }, // TONE_CDMA_MED_S_X4
455 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
456 { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
457 { duration: 500, waveFreq: { 0 }, 0, 0 },
458 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
459 { duration: 25, waveFreq: { 1450, 0 }, 9, 3 },
460 { duration: 500, waveFreq: { 0 }, 0, 0 },
461 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
462 { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
463 { duration: 500, waveFreq: { 0 }, 0, 0 },
464 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
465 { duration: 25, waveFreq: { 1450, 0 }, 9, 9 },
466 { duration: 2500, waveFreq: { 0 }, 0, 0 },
467 { duration: 0, waveFreq: { 0 }, 0, 0 }},
468 repeatCnt: ToneGenerator::TONEGEN_INF,
469 repeatSegment: 0 }, // TONE_CDMA_LOW_S_X4
470 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
471 { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
472 { duration: 2000, waveFreq: { 0 }, 0, 0 },
473 { duration: 0, waveFreq: { 0 }, 0, 0 }},
474 repeatCnt: ToneGenerator::TONEGEN_INF,
475 repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_L
476 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
477 { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
478 { duration: 2000, waveFreq: { 0 }, 0, 0 },
479 { duration: 0, waveFreq: { 0 }, 0, 0 }},
480 repeatCnt: ToneGenerator::TONEGEN_INF,
481 repeatSegment: 0 }, // TONE_CDMA_MED_PBX_L
482 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
483 { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
484 { duration: 2000, waveFreq: { 0 }, 0, 0 },
485 { duration: 0, waveFreq: { 0 }, 0, 0 }},
486 repeatCnt: ToneGenerator::TONEGEN_INF,
487 repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_L
488 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
489 { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
490 { duration: 200, waveFreq: { 0 }, 0, 0 },
491 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
492 { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
493 { duration: 2000, waveFreq: { 0 }, 0, 0 },
494 { duration: 0, waveFreq: { 0 }, 0, 0 }},
495 repeatCnt: ToneGenerator::TONEGEN_INF,
496 repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_SS
497 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
498 { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
499 { duration: 200, waveFreq: { 0 }, 0, 0 },
500 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
501 { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
502 { duration: 2000, waveFreq: { 0 }, 0, 0 },
503 { duration: 0, waveFreq: { 0 }, 0, 0 }},
504 repeatCnt: ToneGenerator::TONEGEN_INF,
505 repeatSegment: 0 }, // TONE_CDMA_MED_PBX_SS
506 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
507 { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
508 { duration: 200, waveFreq: { 0 }, 0, 0 },
509 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
510 { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
511 { duration: 2000, waveFreq: { 0 }, 0, 0 },
512 { duration: 0, waveFreq: { 0 }, 0, 0 }},
513 repeatCnt: ToneGenerator::TONEGEN_INF,
514 repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_SS
515 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
516 { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
517 { duration: 200, waveFreq: { 0 }, 0, 0 },
518 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
519 { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
520 { duration: 200, waveFreq: { 0 }, 0, 0 },
521 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
522 { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
523 { duration: 1000, waveFreq: { 0 }, 0, 0 },
524 { duration: 0, waveFreq: { 0 }, 0, 0 }},
525 repeatCnt: ToneGenerator::TONEGEN_INF,
526 repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_SSL
527 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
528 { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
529 { duration: 200, waveFreq: { 0 }, 0, 0 },
530 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
531 { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
532 { duration: 200, waveFreq: { 0 }, 0, 0 },
533 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
534 { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
535 { duration: 1000, waveFreq: { 0 }, 0, 0 },
536 { duration: 0, waveFreq: { 0 }, 0, 0 }},
537 repeatCnt: ToneGenerator::TONEGEN_INF,
538 repeatSegment: 0 }, // TONE_CDMA_MED_PBX_SSL
539 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
540 { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
541 { duration: 200, waveFreq: { 0 }, 0, 0 },
542 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
543 { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
544 { duration: 200, waveFreq: { 0 }, 0, 0 },
545 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
546 { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
547 { duration: 1000, waveFreq: { 0 }, 0, 0 },
548 { duration: 0, waveFreq: { 0 }, 0, 0 }},
549 repeatCnt: ToneGenerator::TONEGEN_INF,
550 repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_SSL
551 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
552 { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
553 { duration: 200, waveFreq: { 0 }, 0, 0 },
554 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
555 { duration: 25, waveFreq: { 4000, 0 }, 15, 3 },
556 { duration: 200, waveFreq: { 0 }, 0, 0 },
557 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
558 { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
559 { duration: 1000, waveFreq: { 0 }, 0, 0 },
560 { duration: 0, waveFreq: { 0 }, 0, 0 }},
561 repeatCnt: ToneGenerator::TONEGEN_INF,
562 repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_SLS
563 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
564 { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
565 { duration: 200, waveFreq: { 0 }, 0, 0 },
566 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
567 { duration: 25, waveFreq: { 2900, 0 }, 15, 3 },
568 { duration: 200, waveFreq: { 0 }, 0, 0 },
569 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
570 { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
571 { duration: 1000, waveFreq: { 0 }, 0, 0 },
572 { duration: 0, waveFreq: { 0 }, 0, 0 }},
573 repeatCnt: ToneGenerator::TONEGEN_INF,
574 repeatSegment: 0 }, // TONE_CDMA_MED_PBX_SLS
575 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
576 { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
577 { duration: 200, waveFreq: { 0 }, 0, 0 },
578 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
579 { duration: 25, waveFreq: { 1450, 0 }, 15, 3 },
580 { duration: 200, waveFreq: { 0 }, 0, 0 },
581 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
582 { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
583 { duration: 1000, waveFreq: { 0 }, 0, 0 },
584 { duration: 0, waveFreq: { 0 }, 0, 0 }},
585 repeatCnt: ToneGenerator::TONEGEN_INF,
586 repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_SLS
587 { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
588 { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
589 { duration: 200, waveFreq: { 0 }, 0, 0 },
590 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
591 { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
592 { duration: 200, waveFreq: { 0 }, 0, 0 },
593 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
594 { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
595 { duration: 200, waveFreq: { 0 }, 0, 0 },
596 { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
597 { duration: 25, waveFreq: { 4000, 0 }, 7, 9 },
598 { duration: 800, waveFreq: { 0 }, 0, 0 },
599 { duration: 0, waveFreq: { 0 }, 0, 0 }},
600 repeatCnt: ToneGenerator::TONEGEN_INF,
601 repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_S_X4
602 { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
603 { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
604 { duration: 200, waveFreq: { 0 }, 0, 0 },
605 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
606 { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
607 { duration: 200, waveFreq: { 0 }, 0, 0 },
608 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
609 { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
610 { duration: 200, waveFreq: { 0 }, 0, 0 },
611 { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
612 { duration: 25, waveFreq: { 2900, 0 }, 7, 9 },
613 { duration: 800, waveFreq: { 0 }, 0, 0 },
614 { duration: 0, waveFreq: { 0 }, 0, 0 }},
615 repeatCnt: ToneGenerator::TONEGEN_INF,
616 repeatSegment: 0 }, // TONE_CDMA_MED_PBX_S_X4
617 { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
618 { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
619 { duration: 200, waveFreq: { 0 }, 0, 0 },
620 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
621 { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
622 { duration: 200, waveFreq: { 0 }, 0, 0 },
623 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
624 { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
625 { duration: 200, waveFreq: { 0 }, 0, 0 },
626 { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
627 { duration: 25, waveFreq: { 1450, 0 }, 7, 9 },
628 { duration: 800, waveFreq: { 0 }, 0, 0 },
629 { duration: 0, waveFreq: { 0 }, 0, 0 }},
630 repeatCnt: ToneGenerator::TONEGEN_INF,
631 repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_S_X4
632
633 { segments: { { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
634 { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
635 { duration: 62, waveFreq: { 740, 0 }, 0, 0 },
636 { duration: 62, waveFreq: { 622, 0 }, 0, 0 },
637 { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
638 { duration: 0, waveFreq: { 0 }, 0, 0 } },
639 repeatCnt: 0,
640 repeatSegment: 0 }, // TONE_CDMA_ALERT_NETWORK_LITE
641 { segments: { { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
642 { duration: 62, waveFreq: { 659, 0 }, 2, 0 },
643 { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
644 { duration: 0, waveFreq: { 0 }, 0, 0 } },
645 repeatCnt: 0,
646 repeatSegment: 0 }, // TONE_CDMA_ALERT_AUTOREDIAL_LITE
647 { segments: { { duration: 400, waveFreq: { 1150, 770, 0 }, 0, 0 },
648 { duration: 0, waveFreq: { 0 }, 0, 0 } },
649 repeatCnt: 0,
650 repeatSegment: 0 }, // TONE_CDMA_ONE_MIN_BEEP
651 { segments: { { duration: 120, waveFreq: { 941, 1477, 0 }, 0, 0 },
652 { duration: 0, waveFreq: { 0 }, 0, 0 } },
653 repeatCnt: 0,
654 repeatSegment: 0 }, // TONE_CDMA_KEYPAD_VOLUME_KEY_LITE
655 { segments: { { duration: 375, waveFreq: { 587, 0 }, 0, 0 },
656 { duration: 125, waveFreq: { 1175, 0 }, 0, 0 },
657 { duration: 0, waveFreq: { 0 }, 0, 0 } },
658 repeatCnt: 0,
659 repeatSegment: 0 }, // TONE_CDMA_PRESSHOLDKEY_LITE
660 { segments: { { duration: 62, waveFreq: { 587, 0 }, 0, 0 },
661 { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
662 { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
663 { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
664 { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
665 { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
666 { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
667 { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
668 { duration: 0, waveFreq: { 0 }, 0, 0 } },
669 repeatCnt: 0,
670 repeatSegment: 0 }, // TONE_CDMA_ALERT_INCALL_LITE
671 { segments: { { duration: 125, waveFreq: { 941, 0 }, 0, 0 },
672 { duration: 10, waveFreq: { 0 }, 2, 0 },
673 { duration: 4990, waveFreq: { 0 }, 0, 0 },
674 { duration: 0, waveFreq: { 0 }, 0, 0 } },
675 repeatCnt: ToneGenerator::TONEGEN_INF,
676 repeatSegment: 0 }, // TONE_CDMA_EMERGENCY_RINGBACK
677 { segments: { { duration: 125, waveFreq: { 1319, 0 }, 0, 0 },
678 { duration: 125, waveFreq: { 0 }, 0, 0 },
679 { duration: 0, waveFreq: { 0 }, 0, 0 } },
680 repeatCnt: 2,
681 repeatSegment: 0 }, // TONE_CDMA_ALERT_CALL_GUARD
682 { segments: { { duration: 125, waveFreq: { 1047, 0 }, 0, 0 },
683 { duration: 125, waveFreq: { 370, 0 }, 0, 0 },
684 { duration: 0, waveFreq: { 0 }, 0, 0 } },
685 repeatCnt: 0,
686 repeatSegment: 0 }, // TONE_CDMA_SOFT_ERROR_LITE
687 { segments: { { duration: 125, waveFreq: { 1480, 0 }, 0, 0 },
688 { duration: 125, waveFreq: { 1397, 0 }, 0, 0 },
689 { duration: 125, waveFreq: { 784, 0 }, 0, 0 },
690 { duration: 0, waveFreq: { 0 }, 0, 0 } },
691 repeatCnt: 0,
692 repeatSegment: 0 }, // TONE_CDMA_CALLDROP_LITE
693
694 { segments: { { duration: 500, waveFreq: { 425, 0 }, 0, 0 },
695 { duration: 500, waveFreq: { 0 }, 0, 0 },
696 { duration: 0, waveFreq: { 0 }, 0, 0 }},
697 repeatCnt: 0,
698 repeatSegment: 0 }, // TONE_CDMA_NETWORK_BUSY_ONE_SHOT
699 { segments: { { duration: 400, waveFreq: { 1150, 770 }, 0, 0 },
700 { duration: 0, waveFreq: { 0 }, 0, 0 }},
701 repeatCnt: 0,
702 repeatSegment: 0 }, // TONE_CDMA_ABBR_ALERT
703 { segments: { { duration: 0, waveFreq: { 0 }, 0, 0 }},
704 repeatCnt: 0,
705 repeatSegment: 0 }, // TONE_CDMA_SIGNAL_OFF
706
707 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 350, 440, 0 }, 0, 0 },
708 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700709 repeatCnt: ToneGenerator::TONEGEN_INF,
710 repeatSegment: 0 }, // TONE_ANSI_DIAL
David Krauseb6d90ca2009-06-17 15:46:13 -0500711 { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
712 { duration: 500, waveFreq: { 0 }, 0, 0 },
713 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700714 repeatCnt: ToneGenerator::TONEGEN_INF,
715 repeatSegment: 0 }, // TONE_ANSI_BUSY
David Krauseb6d90ca2009-06-17 15:46:13 -0500716 { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
717 { duration: 250, waveFreq: { 0 }, 0, 0 },
718 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700719 repeatCnt: ToneGenerator::TONEGEN_INF,
720 repeatSegment: 0 }, // TONE_ANSI_CONGESTION
David Krauseb6d90ca2009-06-17 15:46:13 -0500721 { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
722 { duration: 9700, waveFreq: { 0 }, 0, 0 },
723 { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
724 { duration: 100, waveFreq: { 0 }, 0, 0 },
725 { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
726 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700727 repeatCnt: ToneGenerator::TONEGEN_INF,
728 repeatSegment: 1 }, // TONE_ANSI_CALL_WAITING
David Krauseb6d90ca2009-06-17 15:46:13 -0500729 { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
730 { duration: 4000, waveFreq: { 0 }, 0, 0 },
731 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700732 repeatCnt: ToneGenerator::TONEGEN_INF,
733 repeatSegment: 0 }, // TONE_ANSI_RINGTONE
David Krauseb6d90ca2009-06-17 15:46:13 -0500734 { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 400, 0 }, 0, 0 },
735 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700736 repeatCnt: ToneGenerator::TONEGEN_INF,
737 repeatSegment: 0 }, // TONE_JAPAN_DIAL
David Krauseb6d90ca2009-06-17 15:46:13 -0500738 { segments: { { duration: 500, waveFreq: { 400, 0 }, 0, 0 },
739 { duration: 500, waveFreq: { 0 }, 0, 0 },
740 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700741 repeatCnt: ToneGenerator::TONEGEN_INF,
742 repeatSegment: 0 }, // TONE_JAPAN_BUSY
David Krauseb6d90ca2009-06-17 15:46:13 -0500743 { segments: { { duration: 1000, waveFreq: { 400, 0 }, 0, 0 },
744 { duration: 2000, waveFreq: { 0 }, 0, 0 },
745 { duration: 0 , waveFreq: { 0 }, 0, 0}},
Eric Laurentf3af7402009-05-05 00:49:01 -0700746 repeatCnt: ToneGenerator::TONEGEN_INF,
747 repeatSegment: 0 }, // TONE_JAPAN_RADIO_ACK
David Krauseb6d90ca2009-06-17 15:46:13 -0500748
749
750
Eric Laurentf3af7402009-05-05 00:49:01 -0700751};
752
753// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
754// to actual tone for current region.
755const unsigned char ToneGenerator::sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES] = {
756 { // ANSI
757 TONE_ANSI_DIAL, // TONE_SUP_DIAL
758 TONE_ANSI_BUSY, // TONE_SUP_BUSY
759 TONE_ANSI_CONGESTION, // TONE_SUP_CONGESTION
760 TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
761 TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
762 TONE_SUP_ERROR, // TONE_SUP_ERROR
763 TONE_ANSI_CALL_WAITING, // TONE_SUP_CALL_WAITING
764 TONE_ANSI_RINGTONE // TONE_SUP_RINGTONE
765 },
766 { // JAPAN
767 TONE_JAPAN_DIAL, // TONE_SUP_DIAL
768 TONE_JAPAN_BUSY, // TONE_SUP_BUSY
769 TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
770 TONE_JAPAN_RADIO_ACK, // TONE_SUP_RADIO_ACK
771 TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
772 TONE_SUP_ERROR, // TONE_SUP_ERROR
773 TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
774 TONE_SUP_RINGTONE // TONE_SUP_RINGTONE
775 }
776};
777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778
779////////////////////////////////////////////////////////////////////////////////
780// ToneGenerator class Implementation
781////////////////////////////////////////////////////////////////////////////////
782
783
784//---------------------------------- public methods ----------------------------
785
786
787////////////////////////////////////////////////////////////////////////////////
788//
789// Method: ToneGenerator::ToneGenerator()
790//
791// Description: Constructor. Initializes the tone sequencer, intantiates required sine wave
792// generators, instantiates output audio track.
793//
794// Input:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795// streamType: Type of stream used for tone playback (enum AudioTrack::stream_type)
796// volume: volume applied to tone (0.0 to 1.0)
797//
798// Output:
799// none
800//
801////////////////////////////////////////////////////////////////////////////////
Eric Laurentbda74692009-11-04 08:27:26 -0800802ToneGenerator::ToneGenerator(int streamType, float volume, bool threadCanCallJava) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803
804 LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume);
805
806 mState = TONE_IDLE;
807
808 if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) {
809 LOGE("Unable to marshal AudioFlinger");
810 return;
811 }
Eric Laurentbda74692009-11-04 08:27:26 -0800812 mThreadCanCallJava = threadCanCallJava;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 mStreamType = streamType;
814 mVolume = volume;
815 mpAudioTrack = 0;
816 mpToneDesc = 0;
817 mpNewToneDesc = 0;
818 // Generate tone by chunks of 20 ms to keep cadencing precision
819 mProcessSize = (mSamplingRate * 20) / 1000;
820
Eric Laurentf3af7402009-05-05 00:49:01 -0700821 char value[PROPERTY_VALUE_MAX];
822 property_get("gsm.operator.iso-country", value, "");
823 if (strcmp(value,"us") == 0 ||
824 strcmp(value,"ca") == 0) {
825 mRegion = ANSI;
826 } else if (strcmp(value,"jp") == 0) {
827 mRegion = JAPAN;
828 } else {
829 mRegion = CEPT;
830 }
831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 if (initAudioTrack()) {
833 LOGV("ToneGenerator INIT OK, time: %d\n", (unsigned int)(systemTime()/1000000));
834 } else {
835 LOGV("!!!ToneGenerator INIT FAILED!!!\n");
836 }
837}
838
839
840
841
842////////////////////////////////////////////////////////////////////////////////
843//
844// Method: ToneGenerator::~ToneGenerator()
845//
846// Description: Destructor. Stop sound playback and delete audio track if
847// needed and delete sine wave generators.
848//
849// Input:
850// none
851//
852// Output:
853// none
854//
855////////////////////////////////////////////////////////////////////////////////
856ToneGenerator::~ToneGenerator() {
857 LOGV("ToneGenerator destructor\n");
858
859 if (mpAudioTrack) {
860 stopTone();
861 LOGV("Delete Track: %p\n", mpAudioTrack);
862 delete mpAudioTrack;
863 }
864}
865
866////////////////////////////////////////////////////////////////////////////////
867//
868// Method: ToneGenerator::startTone()
869//
870// Description: Starts tone playback.
871//
872// Input:
Eric Laurent96c08a62009-09-07 08:38:38 -0700873// toneType: Type of tone generated (values in enum tone_type)
874// durationMs: The tone duration in milliseconds. If the tone is limited in time by definition,
875// the actual duration will be the minimum of durationMs and the defined tone duration.
876// Ommiting or setting durationMs to -1 does not limit tone duration.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877//
878// Output:
879// none
880//
881////////////////////////////////////////////////////////////////////////////////
Eric Laurent96c08a62009-09-07 08:38:38 -0700882bool ToneGenerator::startTone(int toneType, int durationMs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 bool lResult = false;
Eric Laurent62443f52009-10-05 20:29:18 -0700884 status_t lStatus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885
Dave Sparks4c922472009-05-07 09:26:06 -0700886 if ((toneType < 0) || (toneType >= NUM_TONES))
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 return lResult;
888
889 if (mState == TONE_IDLE) {
890 LOGV("startTone: try to re-init AudioTrack");
891 if (!initAudioTrack()) {
892 return lResult;
893 }
894 }
895
896 LOGV("startTone\n");
897
898 mLock.lock();
899
900 // Get descriptor for requested tone
Eric Laurentf3af7402009-05-05 00:49:01 -0700901 toneType = getToneForRegion(toneType);
902 mpNewToneDesc = &sToneDescriptors[toneType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800903
Eric Laurent62443f52009-10-05 20:29:18 -0700904 mDurationMs = durationMs;
905
906 if (mState == TONE_STOPPED) {
907 LOGV("Start waiting for previous tone to stop");
Eric Laurentdd28d562009-10-23 04:46:30 -0700908 lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
Eric Laurent62443f52009-10-05 20:29:18 -0700909 if (lStatus != NO_ERROR) {
910 LOGE("--- start wait for stop timed out, status %d", lStatus);
911 mState = TONE_IDLE;
Eric Laurentdd28d562009-10-23 04:46:30 -0700912 mLock.unlock();
Eric Laurent62443f52009-10-05 20:29:18 -0700913 return lResult;
Eric Laurent96c08a62009-09-07 08:38:38 -0700914 }
Eric Laurent96c08a62009-09-07 08:38:38 -0700915 }
916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 if (mState == TONE_INIT) {
918 if (prepareWave()) {
919 LOGV("Immediate start, time %d\n", (unsigned int)(systemTime()/1000000));
920 lResult = true;
921 mState = TONE_STARTING;
922 mLock.unlock();
923 mpAudioTrack->start();
924 mLock.lock();
925 if (mState == TONE_STARTING) {
926 LOGV("Wait for start callback");
Eric Laurentdd28d562009-10-23 04:46:30 -0700927 lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700928 if (lStatus != NO_ERROR) {
929 LOGE("--- Immediate start timed out, status %d", lStatus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 mState = TONE_IDLE;
931 lResult = false;
932 }
933 }
934 } else {
Eric Laurentc4e58c02009-08-11 01:26:35 -0700935 mState = TONE_IDLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 }
937 } else {
938 LOGV("Delayed start\n");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 mState = TONE_RESTARTING;
Eric Laurentdd28d562009-10-23 04:46:30 -0700940 lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700941 if (lStatus == NO_ERROR) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 if (mState != TONE_IDLE) {
943 lResult = true;
944 }
945 LOGV("cond received");
946 } else {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700947 LOGE("--- Delayed start timed out, status %d", lStatus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 mState = TONE_IDLE;
949 }
950 }
951 mLock.unlock();
952
953 LOGV_IF(lResult, "Tone started, time %d\n", (unsigned int)(systemTime()/1000000));
954 LOGW_IF(!lResult, "Tone start failed!!!, time %d\n", (unsigned int)(systemTime()/1000000));
955
956 return lResult;
957}
958
959////////////////////////////////////////////////////////////////////////////////
960//
961// Method: ToneGenerator::stopTone()
962//
963// Description: Stops tone playback.
964//
965// Input:
966// none
967//
968// Output:
969// none
970//
971////////////////////////////////////////////////////////////////////////////////
972void ToneGenerator::stopTone() {
973 LOGV("stopTone");
974
975 mLock.lock();
976 if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) {
977 mState = TONE_STOPPING;
978 LOGV("waiting cond");
Eric Laurentdd28d562009-10-23 04:46:30 -0700979 status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 if (lStatus == NO_ERROR) {
981 LOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000));
982 } else {
983 LOGE("--- Stop timed out");
984 mState = TONE_IDLE;
985 mpAudioTrack->stop();
986 }
987 }
988
989 clearWaveGens();
990
991 mLock.unlock();
992}
993
994//---------------------------------- private methods ---------------------------
995
996
997
998
999////////////////////////////////////////////////////////////////////////////////
1000//
1001// Method: ToneGenerator::initAudioTrack()
1002//
1003// Description: Allocates and configures AudioTrack used for PCM output.
1004//
1005// Input:
1006// none
1007//
1008// Output:
1009// none
1010//
1011////////////////////////////////////////////////////////////////////////////////
1012bool ToneGenerator::initAudioTrack() {
1013
1014 if (mpAudioTrack) {
1015 delete mpAudioTrack;
1016 mpAudioTrack = 0;
1017 }
1018
1019 // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
Eric Laurentbda74692009-11-04 08:27:26 -08001020 mpAudioTrack = new AudioTrack();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 if (mpAudioTrack == 0) {
1022 LOGE("AudioTrack allocation failed");
1023 goto initAudioTrack_exit;
1024 }
1025 LOGV("Create Track: %p\n", mpAudioTrack);
1026
Eric Laurentbda74692009-11-04 08:27:26 -08001027 mpAudioTrack->set(mStreamType,
1028 0,
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001029 AUDIO_FORMAT_PCM_16_BIT,
1030 AUDIO_CHANNEL_OUT_MONO,
Eric Laurentbda74692009-11-04 08:27:26 -08001031 0,
1032 0,
1033 audioCallback,
1034 this,
1035 0,
1036 0,
1037 mThreadCanCallJava);
1038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 if (mpAudioTrack->initCheck() != NO_ERROR) {
1040 LOGE("AudioTrack->initCheck failed");
1041 goto initAudioTrack_exit;
1042 }
1043
1044 mpAudioTrack->setVolume(mVolume, mVolume);
1045
1046 mState = TONE_INIT;
1047
1048 return true;
1049
1050initAudioTrack_exit:
1051
1052 // Cleanup
1053 if (mpAudioTrack) {
1054 LOGV("Delete Track I: %p\n", mpAudioTrack);
1055 delete mpAudioTrack;
1056 mpAudioTrack = 0;
1057 }
1058
1059 return false;
1060}
1061
1062
1063////////////////////////////////////////////////////////////////////////////////
1064//
1065// Method: ToneGenerator::audioCallback()
1066//
1067// Description: AudioTrack callback implementation. Generates a block of
1068// PCM samples
1069// and manages tone generator sequencer: tones pulses, tone duration...
1070//
1071// Input:
1072// user reference (pointer to our ToneGenerator)
1073// info audio buffer descriptor
1074//
1075// Output:
1076// returned value: always true.
1077//
1078////////////////////////////////////////////////////////////////////////////////
1079void ToneGenerator::audioCallback(int event, void* user, void *info) {
David Krauseb6d90ca2009-06-17 15:46:13 -05001080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 if (event != AudioTrack::EVENT_MORE_DATA) return;
David Krauseb6d90ca2009-06-17 15:46:13 -05001082
Eric Laurentaf141d52009-09-24 07:03:14 -07001083 AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
1085 short *lpOut = buffer->i16;
1086 unsigned int lNumSmp = buffer->size/sizeof(short);
Eric Laurentf3af7402009-05-05 00:49:01 -07001087 const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088
1089 if (buffer->size == 0) return;
1090
1091
1092 // Clear output buffer: WaveGenerator accumulates into lpOut buffer
1093 memset(lpOut, 0, buffer->size);
1094
1095 while (lNumSmp) {
1096 unsigned int lReqSmp = lNumSmp < lpToneGen->mProcessSize*2 ? lNumSmp : lpToneGen->mProcessSize;
1097 unsigned int lGenSmp;
1098 unsigned int lWaveCmd = WaveGenerator::WAVEGEN_CONT;
1099 bool lSignal = false;
David Krauseb6d90ca2009-06-17 15:46:13 -05001100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 lpToneGen->mLock.lock();
1102
Eric Laurentdd28d562009-10-23 04:46:30 -07001103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 // Update pcm frame count and end time (current time at the end of this process)
1105 lpToneGen->mTotalSmp += lReqSmp;
David Krauseb6d90ca2009-06-17 15:46:13 -05001106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 // Update tone gen state machine and select wave gen command
1108 switch (lpToneGen->mState) {
1109 case TONE_PLAYING:
1110 lWaveCmd = WaveGenerator::WAVEGEN_CONT;
1111 break;
1112 case TONE_STARTING:
1113 LOGV("Starting Cbk");
David Krauseb6d90ca2009-06-17 15:46:13 -05001114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 lWaveCmd = WaveGenerator::WAVEGEN_START;
1116 break;
1117 case TONE_STOPPING:
1118 case TONE_RESTARTING:
1119 LOGV("Stop/restart Cbk");
David Krauseb6d90ca2009-06-17 15:46:13 -05001120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 lWaveCmd = WaveGenerator::WAVEGEN_STOP;
1122 lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
1123 break;
Eric Laurentaf141d52009-09-24 07:03:14 -07001124 case TONE_STOPPED:
1125 LOGV("Stopped Cbk");
1126 goto audioCallback_EndLoop;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 default:
1128 LOGV("Extra Cbk");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 goto audioCallback_EndLoop;
1130 }
David Krauseb6d90ca2009-06-17 15:46:13 -05001131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 // Exit if tone sequence is over
Eric Laurent96c08a62009-09-07 08:38:38 -07001133 if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0 ||
1134 lpToneGen->mTotalSmp > lpToneGen->mMaxSmp) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135 if (lpToneGen->mState == TONE_PLAYING) {
David Krauseb6d90ca2009-06-17 15:46:13 -05001136 lpToneGen->mState = TONE_STOPPING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 }
Eric Laurent96c08a62009-09-07 08:38:38 -07001138 if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
1139 goto audioCallback_EndLoop;
1140 }
Eric Laurentaf141d52009-09-24 07:03:14 -07001141 // fade out before stopping if maximum duration reached
Eric Laurent96c08a62009-09-07 08:38:38 -07001142 lWaveCmd = WaveGenerator::WAVEGEN_STOP;
1143 lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 }
David Krauseb6d90ca2009-06-17 15:46:13 -05001145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 if (lpToneGen->mTotalSmp > lpToneGen->mNextSegSmp) {
1147 // Time to go to next sequence segment
David Krauseb6d90ca2009-06-17 15:46:13 -05001148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 LOGV("End Segment, time: %d\n", (unsigned int)(systemTime()/1000000));
David Krauseb6d90ca2009-06-17 15:46:13 -05001150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 lGenSmp = lReqSmp;
Eric Laurentf3af7402009-05-05 00:49:01 -07001152
1153 // If segment, ON -> OFF transition : ramp volume down
1154 if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 lWaveCmd = WaveGenerator::WAVEGEN_STOP;
Eric Laurentf3af7402009-05-05 00:49:01 -07001156 unsigned int lFreqIdx = 0;
1157 unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
1158
1159 while (lFrequency != 0) {
1160 WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
1161 lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
1162 lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
1163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 LOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
1165 }
Eric Laurentf3af7402009-05-05 00:49:01 -07001166
David Krauseb6d90ca2009-06-17 15:46:13 -05001167 // check if we need to loop and loop for the reqd times
1168 if (lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt) {
1169 if (lpToneGen->mLoopCounter < lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt) {
1170 LOGV ("in if loop loopCnt(%d) loopctr(%d), CurSeg(%d) \n",
1171 lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
1172 lpToneGen->mLoopCounter,
1173 lpToneGen->mCurSegment);
1174 lpToneGen->mCurSegment = lpToneDesc->segments[lpToneGen->mCurSegment].loopIndx;
1175 ++lpToneGen->mLoopCounter;
1176 } else {
1177 // completed loop. go to next segment
1178 lpToneGen->mLoopCounter = 0;
1179 lpToneGen->mCurSegment++;
1180 LOGV ("in else loop loopCnt(%d) loopctr(%d), CurSeg(%d) \n",
1181 lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
1182 lpToneGen->mLoopCounter,
1183 lpToneGen->mCurSegment);
1184 }
1185 } else {
1186 lpToneGen->mCurSegment++;
1187 LOGV ("Goto next seg loopCnt(%d) loopctr(%d), CurSeg(%d) \n",
1188 lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
1189 lpToneGen->mLoopCounter,
1190 lpToneGen->mCurSegment);
1191
1192 }
Eric Laurentf3af7402009-05-05 00:49:01 -07001193
1194 // Handle loop if last segment reached
1195 if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 LOGV("Last Seg: %d\n", lpToneGen->mCurSegment);
David Krauseb6d90ca2009-06-17 15:46:13 -05001197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 // Pre increment loop count and restart if total count not reached. Stop sequence otherwise
Eric Laurentf3af7402009-05-05 00:49:01 -07001199 if (++lpToneGen->mCurCount <= lpToneDesc->repeatCnt) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 LOGV("Repeating Count: %d\n", lpToneGen->mCurCount);
David Krauseb6d90ca2009-06-17 15:46:13 -05001201
Eric Laurentf3af7402009-05-05 00:49:01 -07001202 lpToneGen->mCurSegment = lpToneDesc->repeatSegment;
1203 if (lpToneDesc->segments[lpToneDesc->repeatSegment].waveFreq[0] != 0) {
1204 lWaveCmd = WaveGenerator::WAVEGEN_START;
1205 }
David Krauseb6d90ca2009-06-17 15:46:13 -05001206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
1208 (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
David Krauseb6d90ca2009-06-17 15:46:13 -05001209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210 } else {
Eric Laurentf3af7402009-05-05 00:49:01 -07001211 lGenSmp = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 LOGV("End repeat, time: %d\n", (unsigned int)(systemTime()/1000000));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 }
1214 } else {
1215 LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
1216 (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
Eric Laurentf3af7402009-05-05 00:49:01 -07001217 if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
1218 // If next segment is not silent, OFF -> ON transition : reset wave generator
1219 lWaveCmd = WaveGenerator::WAVEGEN_START;
1220
1221 LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
1222 } else {
1223 lGenSmp = 0;
1224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 }
David Krauseb6d90ca2009-06-17 15:46:13 -05001226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 // Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more
1228 lpToneGen->mNextSegSmp
Eric Laurentf3af7402009-05-05 00:49:01 -07001229 += (lpToneDesc->segments[lpToneGen->mCurSegment].duration * lpToneGen->mSamplingRate) / 1000;
David Krauseb6d90ca2009-06-17 15:46:13 -05001230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 } else {
1232 // Inside a segment keep tone ON or OFF
Eric Laurentf3af7402009-05-05 00:49:01 -07001233 if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 lGenSmp = 0; // If odd segment, tone is currently OFF
1235 } else {
1236 lGenSmp = lReqSmp; // If event segment, tone is currently ON
1237 }
1238 }
David Krauseb6d90ca2009-06-17 15:46:13 -05001239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 if (lGenSmp) {
1241 // If samples must be generated, call all active wave generators and acumulate waves in lpOut
Eric Laurentf3af7402009-05-05 00:49:01 -07001242 unsigned int lFreqIdx = 0;
1243 unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
David Krauseb6d90ca2009-06-17 15:46:13 -05001244
Eric Laurentf3af7402009-05-05 00:49:01 -07001245 while (lFrequency != 0) {
1246 WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
Eric Laurentf3af7402009-05-05 00:49:01 -07001248 lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 }
1250 }
David Krauseb6d90ca2009-06-17 15:46:13 -05001251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 lNumSmp -= lReqSmp;
1253 lpOut += lReqSmp;
David Krauseb6d90ca2009-06-17 15:46:13 -05001254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255audioCallback_EndLoop:
David Krauseb6d90ca2009-06-17 15:46:13 -05001256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 switch (lpToneGen->mState) {
1258 case TONE_RESTARTING:
1259 LOGV("Cbk restarting track\n");
1260 if (lpToneGen->prepareWave()) {
1261 lpToneGen->mState = TONE_STARTING;
Eric Laurent5964e732009-07-09 01:56:20 -07001262 // must reload lpToneDesc as prepareWave() may change mpToneDesc
1263 lpToneDesc = lpToneGen->mpToneDesc;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 } else {
1265 LOGW("Cbk restarting prepareWave() failed\n");
1266 lpToneGen->mState = TONE_IDLE;
1267 lpToneGen->mpAudioTrack->stop();
1268 // Force loop exit
1269 lNumSmp = 0;
1270 }
1271 lSignal = true;
1272 break;
1273 case TONE_STOPPING:
Eric Laurentaf141d52009-09-24 07:03:14 -07001274 LOGV("Cbk Stopping\n");
1275 lpToneGen->mState = TONE_STOPPED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 // Force loop exit
1277 lNumSmp = 0;
1278 break;
Eric Laurentaf141d52009-09-24 07:03:14 -07001279 case TONE_STOPPED:
1280 lpToneGen->mState = TONE_INIT;
1281 LOGV("Cbk Stopped track\n");
1282 lpToneGen->mpAudioTrack->stop();
1283 // Force loop exit
1284 lNumSmp = 0;
1285 buffer->size = 0;
1286 lSignal = true;
1287 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 case TONE_STARTING:
1289 LOGV("Cbk starting track\n");
1290 lpToneGen->mState = TONE_PLAYING;
1291 lSignal = true;
1292 break;
Eric Laurentaf141d52009-09-24 07:03:14 -07001293 case TONE_PLAYING:
1294 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001295 default:
Eric Laurentaf141d52009-09-24 07:03:14 -07001296 // Force loop exit
1297 lNumSmp = 0;
1298 buffer->size = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 break;
1300 }
1301
1302 if (lSignal)
1303 lpToneGen->mWaitCbkCond.signal();
1304 lpToneGen->mLock.unlock();
1305 }
1306}
1307
1308
1309////////////////////////////////////////////////////////////////////////////////
1310//
1311// Method: ToneGenerator::prepareWave()
1312//
1313// Description: Prepare wave generators and reset tone sequencer state machine.
Eric Laurentf3af7402009-05-05 00:49:01 -07001314// mpNewToneDesc must have been initialized before calling this function.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315// Input:
1316// none
1317//
1318// Output:
1319// returned value: true if wave generators have been created, false otherwise
1320//
1321////////////////////////////////////////////////////////////////////////////////
1322bool ToneGenerator::prepareWave() {
Eric Laurentf3af7402009-05-05 00:49:01 -07001323 unsigned int segmentIdx = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324
1325 if (!mpNewToneDesc) {
1326 return false;
1327 }
Eric Laurentf3af7402009-05-05 00:49:01 -07001328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 // Remove existing wave generators if any
1330 clearWaveGens();
1331
1332 mpToneDesc = mpNewToneDesc;
1333
Eric Laurent62443f52009-10-05 20:29:18 -07001334 if (mDurationMs == -1) {
1335 mMaxSmp = TONEGEN_INF;
1336 } else {
1337 if (mDurationMs > (int)(TONEGEN_INF / mSamplingRate)) {
1338 mMaxSmp = (mDurationMs / 1000) * mSamplingRate;
1339 } else {
1340 mMaxSmp = (mDurationMs * mSamplingRate) / 1000;
1341 }
1342 LOGV("prepareWave, duration limited to %d ms", mDurationMs);
1343 }
1344
Eric Laurentf3af7402009-05-05 00:49:01 -07001345 while (mpToneDesc->segments[segmentIdx].duration) {
1346 // Get total number of sine waves: needed to adapt sine wave gain.
1347 unsigned int lNumWaves = numWaves(segmentIdx);
1348 unsigned int freqIdx = 0;
1349 unsigned int frequency = mpToneDesc->segments[segmentIdx].waveFreq[freqIdx];
1350 while (frequency) {
1351 // Instantiate a wave generator if ot already done for this frequency
1352 if (mWaveGens.indexOfKey(frequency) == NAME_NOT_FOUND) {
1353 ToneGenerator::WaveGenerator *lpWaveGen =
1354 new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate,
1355 frequency,
1356 TONEGEN_GAIN/lNumWaves);
1357 if (lpWaveGen == 0) {
1358 goto prepareWave_exit;
1359 }
1360 mWaveGens.add(frequency, lpWaveGen);
1361 }
1362 frequency = mpNewToneDesc->segments[segmentIdx].waveFreq[++freqIdx];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
Eric Laurentf3af7402009-05-05 00:49:01 -07001364 segmentIdx++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 }
1366
1367 // Initialize tone sequencer
1368 mTotalSmp = 0;
1369 mCurSegment = 0;
1370 mCurCount = 0;
David Krauseb6d90ca2009-06-17 15:46:13 -05001371 mLoopCounter = 0;
Eric Laurentf3af7402009-05-05 00:49:01 -07001372 if (mpToneDesc->segments[0].duration == TONEGEN_INF) {
1373 mNextSegSmp = TONEGEN_INF;
1374 } else{
1375 mNextSegSmp = (mpToneDesc->segments[0].duration * mSamplingRate) / 1000;
1376 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377
1378 return true;
1379
1380prepareWave_exit:
1381
1382 clearWaveGens();
1383
1384 return false;
1385}
1386
1387
1388////////////////////////////////////////////////////////////////////////////////
1389//
1390// Method: ToneGenerator::numWaves()
1391//
Eric Laurentf3af7402009-05-05 00:49:01 -07001392// Description: Count number of sine waves needed to generate a tone segment (e.g 2 for DTMF).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393//
1394// Input:
Eric Laurentf3af7402009-05-05 00:49:01 -07001395// segmentIdx tone segment index
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396//
1397// Output:
1398// returned value: nummber of sine waves
1399//
1400////////////////////////////////////////////////////////////////////////////////
Eric Laurentf3af7402009-05-05 00:49:01 -07001401unsigned int ToneGenerator::numWaves(unsigned int segmentIdx) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 unsigned int lCnt = 0;
1403
Eric Laurentf3af7402009-05-05 00:49:01 -07001404 if (mpToneDesc->segments[segmentIdx].duration) {
1405 while (mpToneDesc->segments[segmentIdx].waveFreq[lCnt]) {
1406 lCnt++;
1407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 lCnt++;
1409 }
1410
1411 return lCnt;
1412}
1413
1414
1415////////////////////////////////////////////////////////////////////////////////
1416//
1417// Method: ToneGenerator::clearWaveGens()
1418//
1419// Description: Removes all wave generators.
1420//
1421// Input:
1422// none
1423//
1424// Output:
1425// none
1426//
1427////////////////////////////////////////////////////////////////////////////////
1428void ToneGenerator::clearWaveGens() {
1429 LOGV("Clearing mWaveGens:");
1430
Eric Laurentf3af7402009-05-05 00:49:01 -07001431 for (size_t lIdx = 0; lIdx < mWaveGens.size(); lIdx++) {
1432 delete mWaveGens.valueAt(lIdx);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 }
Eric Laurentf3af7402009-05-05 00:49:01 -07001434 mWaveGens.clear();
1435}
1436
1437////////////////////////////////////////////////////////////////////////////////
1438//
1439// Method: ToneGenerator::getToneForRegion()
1440//
1441// Description: Get correct ringtone type according to current region.
1442// The corrected ring tone type is the tone descriptor index in sToneDescriptors[].
1443//
1444// Input:
1445// none
1446//
1447// Output:
1448// none
1449//
1450////////////////////////////////////////////////////////////////////////////////
1451int ToneGenerator::getToneForRegion(int toneType) {
1452 int regionTone;
1453
1454 if (mRegion == CEPT || toneType < FIRST_SUP_TONE || toneType > LAST_SUP_TONE) {
1455 regionTone = toneType;
1456 } else {
1457 regionTone = sToneMappingTable[mRegion][toneType - FIRST_SUP_TONE];
1458 }
1459
1460 LOGV("getToneForRegion, tone %d, region %d, regionTone %d", toneType, mRegion, regionTone);
1461
1462 return regionTone;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463}
1464
1465
1466////////////////////////////////////////////////////////////////////////////////
1467// WaveGenerator::WaveGenerator class Implementation
1468////////////////////////////////////////////////////////////////////////////////
1469
1470//---------------------------------- public methods ----------------------------
1471
1472////////////////////////////////////////////////////////////////////////////////
1473//
1474// Method: WaveGenerator::WaveGenerator()
1475//
1476// Description: Constructor.
1477//
1478// Input:
1479// samplingRate: Output sampling rate in Hz
1480// frequency: Frequency of the sine wave to generate in Hz
1481// volume: volume (0.0 to 1.0)
1482//
1483// Output:
1484// none
1485//
1486////////////////////////////////////////////////////////////////////////////////
1487ToneGenerator::WaveGenerator::WaveGenerator(unsigned short samplingRate,
1488 unsigned short frequency, float volume) {
1489 double d0;
1490 double F_div_Fs; // frequency / samplingRate
1491
1492 F_div_Fs = frequency / (double)samplingRate;
1493 d0 = - (float)GEN_AMP * sin(2 * M_PI * F_div_Fs);
1494 mS2_0 = (short)d0;
1495 mS1 = 0;
1496 mS2 = mS2_0;
1497
1498 mAmplitude_Q15 = (short)(32767. * 32767. * volume / GEN_AMP);
1499 // take some margin for amplitude fluctuation
1500 if (mAmplitude_Q15 > 32500)
1501 mAmplitude_Q15 = 32500;
1502
1503 d0 = 32768.0 * cos(2 * M_PI * F_div_Fs); // Q14*2*cos()
1504 if (d0 > 32767)
1505 d0 = 32767;
1506 mA1_Q14 = (short) d0;
1507
1508 LOGV("WaveGenerator init, mA1_Q14: %d, mS2_0: %d, mAmplitude_Q15: %d\n",
1509 mA1_Q14, mS2_0, mAmplitude_Q15);
1510}
1511
1512////////////////////////////////////////////////////////////////////////////////
1513//
1514// Method: WaveGenerator::~WaveGenerator()
1515//
1516// Description: Destructor.
1517//
1518// Input:
1519// none
1520//
1521// Output:
1522// none
1523//
1524////////////////////////////////////////////////////////////////////////////////
1525ToneGenerator::WaveGenerator::~WaveGenerator() {
1526}
1527
1528////////////////////////////////////////////////////////////////////////////////
1529//
1530// Method: WaveGenerator::getSamples()
1531//
1532// Description: Generates count samples of a sine wave and accumulates
1533// result in outBuffer.
1534//
1535// Input:
1536// outBuffer: Output buffer where to accumulate samples.
1537// count: number of samples to produce.
1538// command: special action requested (see enum gen_command).
1539//
1540// Output:
1541// none
1542//
1543////////////////////////////////////////////////////////////////////////////////
1544void ToneGenerator::WaveGenerator::getSamples(short *outBuffer,
1545 unsigned int count, unsigned int command) {
1546 long lS1, lS2;
1547 long lA1, lAmplitude;
1548 long Sample; // current sample
1549
1550 // init local
1551 if (command == WAVEGEN_START) {
1552 lS1 = (long)0;
1553 lS2 = (long)mS2_0;
1554 } else {
1555 lS1 = (long)mS1;
1556 lS2 = (long)mS2;
1557 }
1558 lA1 = (long)mA1_Q14;
1559 lAmplitude = (long)mAmplitude_Q15;
1560
1561 if (command == WAVEGEN_STOP) {
1562 lAmplitude <<= 16;
1563 if (count == 0) {
1564 return;
1565 }
1566 long dec = lAmplitude/count;
1567 // loop generation
1568 while (count--) {
1569 Sample = ((lA1 * lS1) >> S_Q14) - lS2;
1570 // shift delay
1571 lS2 = lS1;
1572 lS1 = Sample;
1573 Sample = ((lAmplitude>>16) * Sample) >> S_Q15;
1574 *(outBuffer++) += (short)Sample; // put result in buffer
1575 lAmplitude -= dec;
1576 }
1577 } else {
1578 // loop generation
1579 while (count--) {
1580 Sample = ((lA1 * lS1) >> S_Q14) - lS2;
1581 // shift delay
1582 lS2 = lS1;
1583 lS1 = Sample;
1584 Sample = (lAmplitude * Sample) >> S_Q15;
1585 *(outBuffer++) += (short)Sample; // put result in buffer
1586 }
1587 }
1588
1589 // save status
1590 mS1 = (short)lS1;
1591 mS2 = (short)lS2;
1592}
1593
1594} // end namespace android
1595