summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-05-06 15:48:33 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-05-06 15:48:33 -0700
commit56b7eeaa01fa34de1dad1b113f5355e999ee1d10 (patch)
tree56a8306e9e23f0abf2a730fb78c4d0c2b43c6ec0 /media
parent761daf7550c256258886824fdb939b352c5fd08c (diff)
parentf3af740bdfc261b1cb25c0799af780d3753d4518 (diff)
downloadframeworks_base-56b7eeaa01fa34de1dad1b113f5355e999ee1d10.zip
frameworks_base-56b7eeaa01fa34de1dad1b113f5355e999ee1d10.tar.gz
frameworks_base-56b7eeaa01fa34de1dad1b113f5355e999ee1d10.tar.bz2
manual merge f3af740bdfc261b1cb25c0799af780d3753d4518
Merge commit 'f3af740bdfc261b1cb25c0799af780d3753d4518'
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/ToneGenerator.java66
-rw-r--r--media/libmedia/ToneGenerator.cpp427
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java14
3 files changed, 413 insertions, 94 deletions
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index 0901fbf..4b53756 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -130,25 +130,35 @@ public class ToneGenerator
*/
public static final int TONE_DTMF_D = 15;
/**
- * Call supervisory tone, Dial tone: 425Hz, continuous
- *
+ * Call supervisory tone, Dial tone:
+ * CEPT: 425Hz, continuous
+ * ANSI (IS-95): 350Hz+440Hz, continuous
+ * JAPAN: 400Hz, continuous
+ *
* @see #ToneGenerator(int, int)
*/
public static final int TONE_SUP_DIAL = 16;
/**
- * Call supervisory tone, Busy: 425Hz, 500ms ON, 500ms OFF...
- *
+ * Call supervisory tone, Busy:
+ * CEPT: 425Hz, 500ms ON, 500ms OFF...
+ * ANSI (IS-95): 480Hz+620Hz, 500ms ON, 500ms OFF...
+ * JAPAN: 400Hz, 500ms ON, 500ms OFF...
+ *
* @see #ToneGenerator(int, int)
*/
public static final int TONE_SUP_BUSY = 17;
/**
- * Call supervisory tone, Congestion: 425Hz, 200ms ON, 200ms OFF...
+ * Call supervisory tone, Congestion:
+ * CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF...
+ * ANSI (IS-95): 480Hz+620Hz, 250ms ON, 250ms OFF...
*
* @see #ToneGenerator(int, int)
*/
public static final int TONE_SUP_CONGESTION = 18;
/**
- * Call supervisory tone, Radio path acknowlegment : 425Hz, 200ms ON
+ * Call supervisory tone, Radio path acknowlegment :
+ * CEPT, ANSI: 425Hz, 200ms ON
+ * JAPAN: 400Hz, 1s ON, 2s OFF...
*
* @see #ToneGenerator(int, int)
*/
@@ -166,13 +176,17 @@ public class ToneGenerator
*/
public static final int TONE_SUP_ERROR = 21;
/**
- * Call supervisory tone, Call Waiting: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
+ * Call supervisory tone, Call Waiting:
+ * CEPT, JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
+ * ANSI (IS-95): 440 Hz, 300 ms ON, 9.7 s OFF, (100 ms ON, 100 ms OFF, 100 ms ON, 9.7s OFF ...)
*
* @see #ToneGenerator(int, int)
*/
public static final int TONE_SUP_CALL_WAITING = 22;
/**
- * Call supervisory tone, Ring Tone: 425Hz, 1s ON, 4s OFF...
+ * Call supervisory tone, Ring Tone:
+ * CEPT, JAPAN: 425Hz, 1s ON, 4s OFF...
+ * ANSI (IS-95): 440Hz + 480Hz, 2s ON, 4s OFF...
*
* @see #ToneGenerator(int, int)
*/
@@ -207,6 +221,37 @@ public class ToneGenerator
* @see #ToneGenerator(int, int)
*/
public static final int TONE_PROP_BEEP2 = 28;
+ /**
+ * Call supervisory tone (IS-95), intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms
+ *
+ * @see #ToneGenerator(int, int)
+ */
+ public static final int TONE_SUP_INTERCEPT = 29;
+ /**
+ * Call supervisory tone (IS-95), abbreviated intercept: intercept tone limited to 4 seconds
+ *
+ * @see #ToneGenerator(int, int)
+ */
+ public static final int TONE_SUP_INTERCEPT_ABBREV = 30;
+ /**
+ * Call supervisory tone (IS-95), abbreviated congestion: congestion tone limited to 4 seconds
+ *
+ * @see #ToneGenerator(int, int)
+ */
+ public static final int TONE_SUP_CONGESTION_ABBREV = 31;
+ /**
+ * Call supervisory tone (IS-95), confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle
+ *
+ * @see #ToneGenerator(int, int)
+ */
+ public static final int TONE_SUP_CONFIRM = 32;
+ /**
+ * Call supervisory tone (IS-95), pip tone: four bursts of 480 Hz tone (0.1 s on, 0.1 s off).
+ *
+ * @see #ToneGenerator(int, int)
+ */
+ public static final int TONE_SUP_PIP = 33;
+
/** Maximum volume, for use with {@link #ToneGenerator(int,int)} */
public static final int MAX_VOLUME = AudioSystem.MAX_VOLUME;
@@ -258,6 +303,11 @@ public class ToneGenerator
* <li>{@link #TONE_PROP_NACK}
* <li>{@link #TONE_PROP_PROMPT}
* <li>{@link #TONE_PROP_BEEP2}
+ * <li>{@link #TONE_SUP_INTERCEPT}
+ * <li>{@link #TONE_SUP_INTERCEPT_ABBREV}
+ * <li>{@link #TONE_SUP_CONGESTION_ABBREV}
+ * <li>{@link #TONE_SUP_CONFIRM}
+ * <li>{@link #TONE_SUP_PIP}
* </ul>
* @see #ToneGenerator(int, int)
*/
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 8560593..d1789ad 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -24,44 +24,235 @@
#include <sys/resource.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
+#include <cutils/properties.h>
#include "media/ToneGenerator.h"
+
namespace android {
+
// Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details)
-const ToneGenerator::ToneDescriptor
- ToneGenerator::toneDescriptors[NUM_TONES] = {
- // waveFreq[] segments[] repeatCnt
- { { 1336, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_0
- { { 1209, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_1
- { { 1336, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_2
- { { 1477, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_3
- { { 1209, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_4
- { { 1336, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_5
- { { 1477, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_6
- { { 1209, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_7
- { { 1336, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_8
- { { 1477, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_9
- { { 1209, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_S
- { { 1477, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_P
- { { 1633, 697, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_A
- { { 1633, 770, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_B
- { { 1633, 852, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_C
- { { 1633, 941, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_DTMF_D
- { { 425, 0 }, { ToneGenerator::TONEGEN_INF, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_DIAL
- { { 425, 0 }, { 500, 500, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_BUSY
- { { 425, 0 }, { 200, 200, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CONGESTION
- { { 425, 0 }, { 200, 0 }, 0 }, // TONE_SUP_RADIO_ACK
- { { 425, 0 }, { 200, 200, 0 }, 2 }, // TONE_SUP_RADIO_NOTAVAIL
- { { 950, 1400, 1800, 0 }, { 330, 1000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_ERROR
- { { 425, 0 }, { 200, 600, 200, 3000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_CALL_WAITING
- { { 425, 0 }, { 1000, 4000, 0 }, ToneGenerator::TONEGEN_INF }, // TONE_SUP_RINGTONE
- { { 400, 1200, 0 }, { 40, 0 }, 0 }, // TONE_PROP_BEEP
- { { 1200, 0 }, { 100, 100, 0 }, 1 }, // TONE_PROP_ACK
- { { 300, 400, 500, 0 }, { 400, 0 }, 0 }, // TONE_PROP_NACK
- { { 400, 1200, 0 }, { 200, 0 }, 0 }, // TONE_PROP_PROMPT
- { { 400, 1200, 0 }, { 40, 200, 40, 0 }, 0 } // TONE_PROP_BEEP2
- };
+const ToneGenerator::ToneDescriptor ToneGenerator::sToneDescriptors[] = {
+ { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 941, 0 }},
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_0
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_1
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_2
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_3
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_4
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_5
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_6
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_7
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_8
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_9
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 941, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_S
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 941, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_P
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 697, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_A
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 770, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_B
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 852, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_C
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 941, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_D
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_DIAL
+ { segments: { { duration: 500 , waveFreq: { 425, 0 }},
+ { duration: 500, waveFreq: { 0 }},
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_BUSY
+ { segments: { { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 200, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_CONGESTION
+ { segments: { { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_SUP_RADIO_ACK
+ { segments: { { duration: 200, waveFreq: { 425, 0 }},
+ { duration: 200, waveFreq: { 0 }},
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_SUP_RADIO_NOTAVAIL
+ { segments: { { duration: 330, waveFreq: { 950, 1400, 1800, 0 }},
+ { duration: 1000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_ERROR
+ { segments: { { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 600, waveFreq: { 0 } },
+ { duration: 200, waveFreq: { 425, 0 } },
+ { duration: 3000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_CALL_WAITING
+ { segments: { { duration: 1000, waveFreq: { 425, 0 } },
+ { duration: 4000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_RINGTONE
+ { segments: { { duration: 40, waveFreq: { 400, 1200, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_BEEP
+ { segments: { { duration: 100, waveFreq: { 1200, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 1,
+ repeatSegment: 0 }, // TONE_PROP_ACK
+ { segments: { { duration: 400, waveFreq: { 300, 400, 500, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_NACK
+ { segments: { { duration: 200, waveFreq: { 400, 1200, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_PROMPT
+ { segments: { { duration: 40, waveFreq: { 400, 1200, 0 } },
+ { duration: 200, waveFreq: { 0 } },
+ { duration: 40, waveFreq: { 400, 1200, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_BEEP2
+ { segments: { { duration: 250, waveFreq: { 440, 0 } },
+ { duration: 250, waveFreq: { 620, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_INTERCEPT
+ { segments: { { duration: 250, waveFreq: { 440, 0 } },
+ { duration: 250, waveFreq: { 620, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 7,
+ repeatSegment: 0 }, // TONE_SUP_INTERCEPT_ABBREV
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 } },
+ { duration: 250, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 7,
+ repeatSegment: 0 }, // TONE_SUP_CONGESTION_ABBREV
+ { segments: { { duration: 100, waveFreq: { 350, 440, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_SUP_CONFIRM
+ { segments: { { duration: 100, waveFreq: { 480, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: 3,
+ repeatSegment: 0 }, // TONE_SUP_PIP
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 350, 440, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_DIAL
+ { segments: { { duration: 500, waveFreq: { 480, 620, 0 } },
+ { duration: 500, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_BUSY
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 } },
+ { duration: 250, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_CONGESTION
+ { segments: { { duration: 300, waveFreq: { 440, 0 } },
+ { duration: 9700, waveFreq: { 0 } },
+ { duration: 100, waveFreq: { 440, 0 } },
+ { duration: 100, waveFreq: { 0 } },
+ { duration: 100, waveFreq: { 440, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 1 }, // TONE_ANSI_CALL_WAITING
+ { segments: { { duration: 2000, waveFreq: { 440, 480, 0 } },
+ { duration: 4000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_RINGTONE
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 400, 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_DIAL
+ { segments: { { duration: 500, waveFreq: { 400, 0 } },
+ { duration: 500, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_BUSY
+ { segments: { { duration: 1000, waveFreq: { 400, 0 } },
+ { duration: 2000, waveFreq: { 0 } },
+ { duration: 0 , waveFreq: { 0 }}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_RADIO_ACK
+};
+
+// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
+// to actual tone for current region.
+const unsigned char ToneGenerator::sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES] = {
+ { // ANSI
+ TONE_ANSI_DIAL, // TONE_SUP_DIAL
+ TONE_ANSI_BUSY, // TONE_SUP_BUSY
+ TONE_ANSI_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_ANSI_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_ANSI_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // JAPAN
+ TONE_JAPAN_DIAL, // TONE_SUP_DIAL
+ TONE_JAPAN_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_JAPAN_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_SUP_RINGTONE // TONE_SUP_RINGTONE
+ }
+};
+
////////////////////////////////////////////////////////////////////////////////
// ToneGenerator class Implementation
@@ -105,6 +296,17 @@ ToneGenerator::ToneGenerator(int streamType, float volume) {
// Generate tone by chunks of 20 ms to keep cadencing precision
mProcessSize = (mSamplingRate * 20) / 1000;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("gsm.operator.iso-country", value, "");
+ if (strcmp(value,"us") == 0 ||
+ strcmp(value,"ca") == 0) {
+ mRegion = ANSI;
+ } else if (strcmp(value,"jp") == 0) {
+ mRegion = JAPAN;
+ } else {
+ mRegion = CEPT;
+ }
+
if (initAudioTrack()) {
LOGV("ToneGenerator INIT OK, time: %d\n", (unsigned int)(systemTime()/1000000));
} else {
@@ -170,7 +372,8 @@ bool ToneGenerator::startTone(int toneType) {
mLock.lock();
// Get descriptor for requested tone
- mpNewToneDesc = &toneDescriptors[toneType];
+ toneType = getToneForRegion(toneType);
+ mpNewToneDesc = &sToneDescriptors[toneType];
if (mState == TONE_INIT) {
if (prepareWave()) {
@@ -333,6 +536,7 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
short *lpOut = buffer->i16;
unsigned int lNumSmp = buffer->size/sizeof(short);
+ const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc;
if (buffer->size == 0) return;
@@ -377,7 +581,7 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
// Exit if tone sequence is over
- if (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] == 0) {
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
if (lpToneGen->mState == TONE_PLAYING) {
lpToneGen->mState = TONE_STOPPING;
}
@@ -390,52 +594,64 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
LOGV("End Segment, time: %d\n", (unsigned int)(systemTime()/1000000));
lGenSmp = lReqSmp;
-
- if (lpToneGen->mCurSegment & 0x0001) {
- // If odd segment, OFF -> ON transition : reset wave generator
- lWaveCmd = WaveGenerator::WAVEGEN_START;
-
- LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
- } else {
- // If even segment, ON -> OFF transition : ramp volume down
+
+ // If segment, ON -> OFF transition : ramp volume down
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
lWaveCmd = WaveGenerator::WAVEGEN_STOP;
-
+ unsigned int lFreqIdx = 0;
+ unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
+
+ while (lFrequency != 0) {
+ WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
+ lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
+ lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
+ }
LOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
}
-
- // Pre increment segment index and handle loop if last segment reached
- if (lpToneGen->mpToneDesc->segments[++lpToneGen->mCurSegment] == 0) {
+
+ // Go to next segment
+ lpToneGen->mCurSegment++;
+
+ // Handle loop if last segment reached
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
LOGV("Last Seg: %d\n", lpToneGen->mCurSegment);
// Pre increment loop count and restart if total count not reached. Stop sequence otherwise
- if (++lpToneGen->mCurCount <= lpToneGen->mpToneDesc->repeatCnt) {
+ if (++lpToneGen->mCurCount <= lpToneDesc->repeatCnt) {
LOGV("Repeating Count: %d\n", lpToneGen->mCurCount);
- lpToneGen->mCurSegment = 0;
+ lpToneGen->mCurSegment = lpToneDesc->repeatSegment;
+ if (lpToneDesc->segments[lpToneDesc->repeatSegment].waveFreq[0] != 0) {
+ lWaveCmd = WaveGenerator::WAVEGEN_START;
+ }
LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
(lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
} else {
+ lGenSmp = 0;
LOGV("End repeat, time: %d\n", (unsigned int)(systemTime()/1000000));
-
- // Cancel OFF->ON transition in case previous segment tone state was OFF
- if (!(lpToneGen->mCurSegment & 0x0001)) {
- lGenSmp = 0;
- }
}
} else {
LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
(lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
+ // If next segment is not silent, OFF -> ON transition : reset wave generator
+ lWaveCmd = WaveGenerator::WAVEGEN_START;
+
+ LOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
+ } else {
+ lGenSmp = 0;
+ }
}
// Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more
lpToneGen->mNextSegSmp
- += (lpToneGen->mpToneDesc->segments[lpToneGen->mCurSegment] * lpToneGen->mSamplingRate) / 1000;
+ += (lpToneDesc->segments[lpToneGen->mCurSegment].duration * lpToneGen->mSamplingRate) / 1000;
} else {
// Inside a segment keep tone ON or OFF
- if (lpToneGen->mCurSegment & 0x0001) {
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] == 0) {
lGenSmp = 0; // If odd segment, tone is currently OFF
} else {
lGenSmp = lReqSmp; // If event segment, tone is currently ON
@@ -444,11 +660,13 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
if (lGenSmp) {
// If samples must be generated, call all active wave generators and acumulate waves in lpOut
- unsigned int lWaveIdx;
+ unsigned int lFreqIdx = 0;
+ unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
- for (lWaveIdx = 0; lWaveIdx < (unsigned int)lpToneGen->mWaveGens.size(); lWaveIdx++) {
- WaveGenerator *lpWaveGen = lpToneGen->mWaveGens[lWaveIdx];
+ while (lFrequency != 0) {
+ WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
+ lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
}
}
@@ -501,7 +719,7 @@ audioCallback_EndLoop:
// Method: ToneGenerator::prepareWave()
//
// Description: Prepare wave generators and reset tone sequencer state machine.
-// mpNewToneDesc must have been initialized befoire calling this function.
+// mpNewToneDesc must have been initialized before calling this function.
// Input:
// none
//
@@ -510,40 +728,48 @@ audioCallback_EndLoop:
//
////////////////////////////////////////////////////////////////////////////////
bool ToneGenerator::prepareWave() {
- unsigned int lCnt = 0;
- unsigned int lNumWaves;
+ unsigned int segmentIdx = 0;
if (!mpNewToneDesc) {
return false;
}
+
// Remove existing wave generators if any
clearWaveGens();
mpToneDesc = mpNewToneDesc;
- // Get total number of sine waves: needed to adapt sine wave gain.
- lNumWaves = numWaves();
-
- // Instantiate as many wave generators as listed in descriptor
- while (lCnt < lNumWaves) {
- ToneGenerator::WaveGenerator *lpWaveGen =
- new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate,
- mpToneDesc->waveFreq[lCnt],
- TONEGEN_GAIN/lNumWaves);
- if (lpWaveGen == 0) {
- goto prepareWave_exit;
+ while (mpToneDesc->segments[segmentIdx].duration) {
+ // Get total number of sine waves: needed to adapt sine wave gain.
+ unsigned int lNumWaves = numWaves(segmentIdx);
+ unsigned int freqIdx = 0;
+ unsigned int frequency = mpToneDesc->segments[segmentIdx].waveFreq[freqIdx];
+ while (frequency) {
+ // Instantiate a wave generator if ot already done for this frequency
+ if (mWaveGens.indexOfKey(frequency) == NAME_NOT_FOUND) {
+ ToneGenerator::WaveGenerator *lpWaveGen =
+ new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate,
+ frequency,
+ TONEGEN_GAIN/lNumWaves);
+ if (lpWaveGen == 0) {
+ goto prepareWave_exit;
+ }
+ mWaveGens.add(frequency, lpWaveGen);
+ }
+ frequency = mpNewToneDesc->segments[segmentIdx].waveFreq[++freqIdx];
}
-
- mWaveGens.push(lpWaveGen);
- LOGV("Create sine: %d\n", mpToneDesc->waveFreq[lCnt]);
- lCnt++;
+ segmentIdx++;
}
// Initialize tone sequencer
mTotalSmp = 0;
mCurSegment = 0;
mCurCount = 0;
- mNextSegSmp = (mpToneDesc->segments[0] * mSamplingRate) / 1000;
+ if (mpToneDesc->segments[0].duration == TONEGEN_INF) {
+ mNextSegSmp = TONEGEN_INF;
+ } else{
+ mNextSegSmp = (mpToneDesc->segments[0].duration * mSamplingRate) / 1000;
+ }
return true;
@@ -559,19 +785,22 @@ prepareWave_exit:
//
// Method: ToneGenerator::numWaves()
//
-// Description: Count number of sine waves needed to generate tone (e.g 2 for DTMF).
+// Description: Count number of sine waves needed to generate a tone segment (e.g 2 for DTMF).
//
// Input:
-// none
+// segmentIdx tone segment index
//
// Output:
// returned value: nummber of sine waves
//
////////////////////////////////////////////////////////////////////////////////
-unsigned int ToneGenerator::numWaves() {
+unsigned int ToneGenerator::numWaves(unsigned int segmentIdx) {
unsigned int lCnt = 0;
- while (mpToneDesc->waveFreq[lCnt]) {
+ if (mpToneDesc->segments[segmentIdx].duration) {
+ while (mpToneDesc->segments[segmentIdx].waveFreq[lCnt]) {
+ lCnt++;
+ }
lCnt++;
}
@@ -595,10 +824,38 @@ unsigned int ToneGenerator::numWaves() {
void ToneGenerator::clearWaveGens() {
LOGV("Clearing mWaveGens:");
- while (!mWaveGens.isEmpty()) {
- delete mWaveGens.top();
- mWaveGens.pop();
+ for (size_t lIdx = 0; lIdx < mWaveGens.size(); lIdx++) {
+ delete mWaveGens.valueAt(lIdx);
}
+ mWaveGens.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::getToneForRegion()
+//
+// Description: Get correct ringtone type according to current region.
+// The corrected ring tone type is the tone descriptor index in sToneDescriptors[].
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+int ToneGenerator::getToneForRegion(int toneType) {
+ int regionTone;
+
+ if (mRegion == CEPT || toneType < FIRST_SUP_TONE || toneType > LAST_SUP_TONE) {
+ regionTone = toneType;
+ } else {
+ regionTone = sToneMappingTable[mRegion][toneType - FIRST_SUP_TONE];
+ }
+
+ LOGV("getToneForRegion, tone %d, region %d, regionTone %d", toneType, mRegion, regionTone);
+
+ return regionTone;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
index da18e74..c75b96b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/TonesAutoTest.java
@@ -74,7 +74,19 @@ import android.media.AudioManager;
break;
}
}
-
+
+ for (type = ToneGenerator.TONE_SUP_INTERCEPT;
+ type <= ToneGenerator.TONE_SUP_PIP; type++) {
+ if (toneGen.startTone(type)) {
+ Thread.sleep(5000);
+ toneGen.stopTone();
+ Thread.sleep(200);
+ } else {
+ result = false;
+ break;
+ }
+ }
+
toneGen.release();
return result;
}