Файлы TextToSpeech, playEarcon и .wav

В одном из моих приложений у меня есть упражнение, в котором речь синтезирует буквенно-цифровые ссылочные строки, буква / цифра буквой / цифрой, например, «ABC123» звучит как «Да, пчела, море, один, два, три» . Поскольку это ограниченный набор звуков, я подумал, что было бы неплохо включить движок TTS для работы без подключения к Интернету, воспроизводя предварительно записанные файлы .wav с цифрами и буквами с помощью метода playEarcon.

Я поместил все 36 файлов wav в папку res / raw и сопоставил идентификаторы ресурсов с буквами при инициализации механизма TTS. Это работает хорошо, однако .apk теперь намного больше, так как файлы wav хранятся в несжатом виде в apk. Хотелось бы сделать размер apk меньше.

В ответе на другой вопрос говорится, что файлы wav исключены из сжатия.(Я не понимаю, почему, поскольку они обычно сокращаются до примерно 40% от оригинала). Если посмотреть на внутренности apk, это, похоже, правда.

Поскольку расширение файлов ресурсов не упоминается в коде, я попытался переименовать файлы wav в различные форматы .waw, .abc, .spc. Все они сжимаются, но, к сожалению, метод playEarcon не производит звука при вызове, если только расширение не является .wav.

Короче говоря, я хотел бы заставить движок TTS воспроизводить файлы без расширения wav или убедить его сжать файлы .wav.

Все предложения будут приняты с благодарностью. Как бы то ни было, я публикую ниже самый маленький наглядный пример кода. Мои рабочие файлы называются gb_a.wav, gb_b.wav и т.д. При изменении расширения они перестают звучать.

public class WavSpeakerActivity extends Activity implements
        RadioGroup.OnCheckedChangeListener, TextToSpeech.OnInitListener {

    static final int mGBLetterResIds[] = { R.raw.gb_a, R.raw.gb_b, R.raw.gb_c,
            R.raw.gb_d, R.raw.gb_e, R.raw.gb_f, R.raw.gb_g, R.raw.gb_h,
            R.raw.gb_i, R.raw.gb_j, R.raw.gb_k, R.raw.gb_l, R.raw.gb_m,
            R.raw.gb_n, R.raw.gb_o, R.raw.gb_p, R.raw.gb_q, R.raw.gb_r,
            R.raw.gb_s, R.raw.gb_t, R.raw.gb_u, R.raw.gb_v, R.raw.gb_w,
            R.raw.gb_x, R.raw.gb_y, R.raw.gb_z };
    static final int mGBNumberResIds[] = { R.raw.gb_zero, R.raw.gb_one,
            R.raw.gb_two, R.raw.gb_three, R.raw.gb_four, R.raw.gb_five,
            R.raw.gb_six, R.raw.gb_seven, R.raw.gb_eight, R.raw.gb_nine };

    static final String mGbStr = "GB";
    static final String mAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static final String mNumbers = "0123456789";
    private String mPpackageName = null;
    private String mTextToSpeak = null;
    private RadioGroup mRadioGroup = null;// two buttons one sets letters, the other numbers
    private TextToSpeech mTts = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mTts = new TextToSpeech(this, this);
        mRadioGroup = (RadioGroup) findViewById(R.id.radioGroup1);
        mRadioGroup.setOnCheckedChangeListener(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        RadioGroup rg = (RadioGroup) findViewById(R.id.radioGroup1);
        switchText(rg);
        mPpackageName = getPackageName();
    }

    @Override
    public void onDestroy() {
        // Don't forget to shutdown speech engine
        if (mTts != null) {
            mTts.stop();
            mTts.shutdown();
        }
        super.onDestroy();
    }

    private void switchText(RadioGroup rg) {
        // select letters or digits as the String to speak
        int checkedButton = rg.getCheckedRadioButtonId();
        switch (checkedButton) {
            case R.id.alphabet:
                mTextToSpeak = mAlphabet;
                break;
            case R.id.numbers:
                mTextToSpeak = mNumbers;
                break;
        }
    }

    public void myClickHandler(View target) {
        // Just the one button has been clicked - the 'Speak' one
        String earconKey;
        String lang = Locale.UK.getCountry(); // will be "GB", just have UK in this small example
        mTts.setLanguage(Locale.UK); // skip error checking for brevity's sake
        String text = mTextToSpeak.replaceAll("\\s", "");// remove spaces (if any)
        char c;
        for (int i = 0; i < text.length(); i++) {
            c = text.charAt(i);
            if ( Character.isLetter(c) || Character.isDigit(c) ) {
                earconKey = lang + Character.toString(c); // GBA, GBB..GBZ, GB0.. GB9
                mTts.playEarcon(earconKey, TextToSpeech.QUEUE_ADD, null);
            }
        }
    }

    @Override
    public void onInit(int status) {
        // doesn't seem we need to check status or setLanguage if we're just playing earcons
        mapEarCons(); // map letter/digit sounds to resource ids
    }

    private void mapEarCons() {
        String key;
        for (char c = 'A'; c <= 'Z' ; c++){
            key = mGbStr + Character.toString(c); // GBA, GBB .. GBZ
            mTts.addEarcon(key, mPpackageName, mGBLetterResIds[c - 'A'] );// add it
        }
        for (int i = 0 ; i <= 9; i++){
            key = mGbStr + Integer.toString(i); // GB0, GB1 .. GB9
            mTts.addEarcon(key, mPpackageName, mGBNumberResIds[i] );
        }
    }

    @Override
    public void onCheckedChanged(RadioGroup rg, int arg1) { switchText(rg); }
}

. .

6
задан Community 23 May 2017 в 12:03
поделиться