Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a24b50be authored by Niels Egberts's avatar Niels Egberts
Browse files

Restrict audioformat to 8bit, 16bit or float PCM with an annotation and

a warning.

TextToSpeech.synthesizeToFile has only ever worked with 8bit and 16bit
PCM. In case of float PCM an invalid file would be generated and in case
of other encodings the TTS engine would crash.

Also add more annotations to SynthesisCallback.

Change-Id: I1c44a44509e9b53bb2e1b0f2044b1a5919875e1c
parent f1e52016
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -107,6 +107,14 @@ class FileSynthesisCallback extends AbstractSynthesisCallback {
            Log.d(TAG, "FileSynthesisRequest.start(" + sampleRateInHz + "," + audioFormat
                    + "," + channelCount + ")");
        }
        if (audioFormat != AudioFormat.ENCODING_PCM_8BIT ||
            audioFormat != AudioFormat.ENCODING_PCM_16BIT ||
            audioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
            Log.e(TAG, "Audio format encoding " + audioFormat + " not supported. Please use one " +
                       "of AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT or " +
                       "AudioFormat.ENCODING_PCM_FLOAT");
        }

        FileChannel fileChannel = null;
        synchronized (mStateLock) {
            if (mStatusCode == TextToSpeech.STOPPED) {
+8 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package android.speech.tts;

import android.media.AudioFormat;
import android.speech.tts.TextToSpeechService.AudioOutputParams;
import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher;
import android.util.Log;
@@ -122,6 +123,13 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
    public int start(int sampleRateInHz, int audioFormat, int channelCount) {
        if (DBG) Log.d(TAG, "start(" + sampleRateInHz + "," + audioFormat + "," + channelCount
                + ")");
        if (audioFormat != AudioFormat.ENCODING_PCM_8BIT ||
            audioFormat != AudioFormat.ENCODING_PCM_16BIT ||
            audioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
            Log.w(TAG, "Audio format encoding " + audioFormat + " not supported. Please use one " +
                       "of AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT or " +
                       "AudioFormat.ENCODING_PCM_FLOAT");
        }

        int channelConfig = BlockingAudioTrack.getChannelConfig(channelCount);

+23 −3
Original line number Diff line number Diff line
@@ -15,6 +15,14 @@
 */
package android.speech.tts;

import android.annotation.IntDef;
import android.annotation.IntRange;
import android.media.AudioFormat;
import android.speech.tts.TextToSpeech;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * A callback to return speech data synthesized by a text to speech engine.
 *
@@ -31,6 +39,13 @@ package android.speech.tts;
 * All methods can be only called on the synthesis thread.
 */
public interface SynthesisCallback {

     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT,
              AudioFormat.ENCODING_PCM_FLOAT})
     public @interface SupportedAudioFormat {};

    /**
     * @return the maximum number of bytes that the TTS engine can pass in a single call of
     *         {@link #audioAvailable}. Calls to {@link #audioAvailable} with data lengths
@@ -38,6 +53,7 @@ public interface SynthesisCallback {
     */
    public int getMaxBufferSize();

    // TODO: Replace reference to Android N to an API level when the API level for N is decided.
    /**
     * The service should call this when it starts to synthesize audio for this
     * request.
@@ -47,12 +63,16 @@ public interface SynthesisCallback {
     *
     * @param sampleRateInHz Sample rate in HZ of the generated audio.
     * @param audioFormat Audio format of the generated audio. Must be one of
     *         the ENCODING_ constants defined in {@link android.media.AudioFormat}.
     *         {@link android.media.AudioFormat.ENCODING_PCM_8BIT} or
     *         {@link android.media.AudioFormat.ENCODING_PCM_16BIT}. Or
     *         {@link android.media.AudioFormat.ENCODING_PCM_FLOAT} when targetting Android N and
     *         above.
     * @param channelCount The number of channels. Must be {@code 1} or {@code 2}.
     * @return {@link TextToSpeech#SUCCESS}, {@link TextToSpeech#ERROR} or
     *          {@link TextToSpeech#STOPPED}.
     */
    public int start(int sampleRateInHz, int audioFormat, int channelCount);
    public int start(int sampleRateInHz, @SupportedAudioFormat int audioFormat,
                     @IntRange(from=1,to=2) int channelCount);

    /**
     * The service should call this method when synthesized audio is ready for consumption.
@@ -102,7 +122,7 @@ public interface SynthesisCallback {
     * @param errorCode Error code to pass to the client. One of the ERROR_ values from
     *      {@link TextToSpeech}
     */
    public void error(int errorCode);
    public void error(@TextToSpeech.Error int errorCode);

    /**
     * Check if {@link #start} was called or not.
+9 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package android.speech.tts;

import android.annotation.IntDef;
import android.annotation.RawRes;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -38,6 +39,8 @@ import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -75,6 +78,12 @@ public class TextToSpeech {
     */
    public static final int STOPPED = -2;

    /** @hide */
    @IntDef({ERROR_SYNTHESIS, ERROR_SERVICE, ERROR_OUTPUT, ERROR_NETWORK, ERROR_NETWORK_TIMEOUT,
             ERROR_INVALID_REQUEST, ERROR_NOT_INSTALLED_YET})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Error {}

    /**
     * Denotes a failure of a TTS engine to synthesize the given input.
     */