summaryrefslogtreecommitdiffstats
path: root/media/libmedia/ToneGenerator.cpp
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2013-03-27 12:05:40 -0700
committerEric Laurent <elaurent@google.com>2013-03-27 18:12:22 -0700
commit681be0398a06da7e24db4ed934a92af64d1409b1 (patch)
treee8b59b31d995c5cbd12c8c0f7dc6a28eeb184c75 /media/libmedia/ToneGenerator.cpp
parent2d595c0efc0eee9e0c94f4842c6fed07c19163c1 (diff)
downloadframeworks_av-681be0398a06da7e24db4ed934a92af64d1409b1.zip
frameworks_av-681be0398a06da7e24db4ed934a92af64d1409b1.tar.gz
frameworks_av-681be0398a06da7e24db4ed934a92af64d1409b1.tar.bz2
ToneGenerator: fix truncated tones
The first DTMF tone after a silent period is truncated. This is because the phone app starts and stops the tone when the user presses and releases the key. This combined to the fact that the tones use the low latency path and that when the output stream exists standby there is a period of several milliseconds during which no audio is mixed until the stream is "warmed up". The result is that much less audio is generated than the actual key press duration. The fix consists in storing the tone start time and making sure that the number of samples generated corresponds at least to the time difference between the tone start and stop commands. Bug 6607077 Change-Id: I070d20dd8600c25a9e5d5a60c1d3313b7917b00d
Diffstat (limited to 'media/libmedia/ToneGenerator.cpp')
-rw-r--r--media/libmedia/ToneGenerator.cpp32
1 files changed, 31 insertions, 1 deletions
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 3554608..9ea3ea7 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -922,6 +922,9 @@ bool ToneGenerator::startTone(tone_type toneType, int durationMs) {
ALOGV("Immediate start, time %d", (unsigned int)(systemTime()/1000000));
lResult = true;
mState = TONE_STARTING;
+ if (clock_gettime(CLOCK_MONOTONIC, &mStartTime) != 0) {
+ mStartTime.tv_sec = 0;
+ }
mLock.unlock();
mpAudioTrack->start();
mLock.lock();
@@ -940,6 +943,7 @@ bool ToneGenerator::startTone(tone_type toneType, int durationMs) {
} else {
ALOGV("Delayed start");
mState = TONE_RESTARTING;
+ mStartTime.tv_sec = 0;
lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
if (lStatus == NO_ERROR) {
if (mState != TONE_IDLE) {
@@ -978,7 +982,30 @@ void ToneGenerator::stopTone() {
mLock.lock();
if (mState != TONE_IDLE && mState != TONE_INIT) {
if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) {
- mState = TONE_STOPPING;
+ struct timespec stopTime;
+ // If the start time is valid, make sure that the number of audio samples produced
+ // corresponds at least to the time between the start and stop commands.
+ // This is needed in case of cold start of the output stream.
+ if ((mStartTime. tv_sec != 0) && (clock_gettime(CLOCK_MONOTONIC, &stopTime) == 0)) {
+ time_t sec = stopTime.tv_sec - mStartTime.tv_sec;
+ long nsec = stopTime.tv_nsec - mStartTime.tv_nsec;
+ long durationMs;
+ if (nsec < 0) {
+ --sec;
+ nsec += 1000000000;
+ }
+
+ if ((sec + 1) > ((long)(INT_MAX / mSamplingRate))) {
+ mMaxSmp = sec * mSamplingRate;
+ } else {
+ // mSamplingRate is always > 1000
+ sec = sec * 1000 + nsec / 1000000; // duration in milliseconds
+ mMaxSmp = (sec * mSamplingRate) / 1000;
+ }
+ ALOGV("stopTone() forcing mMaxSmp to %d, total for far %d", mMaxSmp, mTotalSmp);
+ } else {
+ mState = TONE_STOPPING;
+ }
}
ALOGV("waiting cond");
status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
@@ -1263,6 +1290,9 @@ audioCallback_EndLoop:
ALOGV("Cbk restarting track");
if (lpToneGen->prepareWave()) {
lpToneGen->mState = TONE_STARTING;
+ if (clock_gettime(CLOCK_MONOTONIC, &lpToneGen->mStartTime) != 0) {
+ lpToneGen->mStartTime.tv_sec = 0;
+ }
// must reload lpToneDesc as prepareWave() may change mpToneDesc
lpToneDesc = lpToneGen->mpToneDesc;
} else {