Fixed Issue #47 (say command should use Voice with the default language) and Issue #53 (say command should use a 'concrete' AudioFormat)

This commit is contained in:
Kelly Davis 2016-05-24 16:18:57 +02:00 коммит произвёл Tilman Kamp
Родитель d9c3fc0849
Коммит fee9c85f49
1 изменённых файлов: 114 добавлений и 1 удалений

Просмотреть файл

@ -7,9 +7,11 @@
*/
package org.eclipse.smarthome.io.voice.internal.extensions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.eclipse.smarthome.core.items.Item;
@ -77,8 +79,12 @@ public class SayConsoleCommandExtension extends AbstractConsoleCommandExtension
if (ttsService != null) {
Set<Voice> voices = ttsService.getAvailableVoices();
Set<AudioFormat> audioFormats = ttsService.getSupportedFormats();
Voice voice = getPreferedVoice(voices);
AudioFormat audioFormat = getPreferedAudioFormat(audioFormats);
try {
AudioSource audioSource = ttsService.synthesize(msg.toString(), voices.iterator().next(), audioFormats.iterator().next());
AudioSource audioSource = ttsService.synthesize(msg.toString(), voice, audioFormat);
AudioPlayer audioPlayer = new AudioPlayer(audioSource);
audioPlayer.start();
audioPlayer.join();
@ -93,6 +99,113 @@ public class SayConsoleCommandExtension extends AbstractConsoleCommandExtension
}
}
protected Voice getPreferedVoice(Set<Voice> voices) {
// Express preferences with a Language Priority List
Locale locale = Locale.getDefault();
String ranges = locale.toLanguageTag();
List<Locale.LanguageRange> languageRanges = Locale.LanguageRange.parse(ranges);
// Get collection of voice locales
Collection<Locale> locales = new ArrayList<Locale>();
for (Voice currentVoice : voices) {
locales.add(currentVoice.getLocale());
}
// Determine prefered locale based on RFC 4647
Locale preferedLocale = Locale.lookup(languageRanges,locales);
// As a last resort choose some Locale
if (null == preferedLocale) {
preferedLocale = locales.iterator().next();
}
// Determine prefered voice
Voice preferedVoice = null;
for (Voice currentVoice : voices) {
if (preferedLocale.equals(currentVoice.getLocale())) {
preferedVoice = currentVoice;
}
}
assert (preferedVoice != null);
// Return prefered voice
return preferedVoice;
}
protected AudioFormat getPreferedAudioFormat(Set<AudioFormat> audioFormats) {
// Return the first concrete AudioFormat found
for (AudioFormat currentAudioFormat : audioFormats) {
// Check if currentAudioFormat is abstract
if (null == currentAudioFormat.getCodec()) { continue; }
if (null == currentAudioFormat.getContainer()) { continue; }
if (null == currentAudioFormat.isBigEndian()) { continue; }
if (null == currentAudioFormat.getBitDepth()) { continue; }
if (null == currentAudioFormat.getBitRate()) { continue; }
if (null == currentAudioFormat.getFrequency()) { continue; }
// Prefer WAVE container
if (!currentAudioFormat.getContainer().equals("WAVE")) { continue; }
// As currentAudioFormat is concreate, use it
return currentAudioFormat;
}
// There's no concrete AudioFormat so we must create one
for (AudioFormat currentAudioFormat : audioFormats) {
// Define AudioFormat to return
AudioFormat format = currentAudioFormat;
// Not all Codecs and containers can be supported
if (null == format.getCodec()) { continue; }
if (null == format.getContainer()) { continue; }
// Prefer WAVE container
if (!format.getContainer().equals("WAVE")) { continue; }
// If required set BigEndian, BitDepth, BitRate, and Frequency to default values
if (null == format.isBigEndian()) {
format = new AudioFormat(format.getContainer(), format.getCodec(), new Boolean(true), format.getBitDepth(), format.getBitRate(), format.getFrequency());
}
if (null == format.getBitDepth() || null == format.getBitRate() || null == format.getFrequency()) {
// Define default values
int defaultBitDepth = 16;
int defaultBitRate = 262144;
long defaultFrequency = 16384;
// Obtain current values
Integer bitRate = format.getBitRate();
Long frequency = format.getFrequency();
Integer bitDepth = format.getBitDepth();
// These values must be interdependent (bitRate = bitDepth * frequency)
if (null == bitRate) {
if (null == bitDepth) { bitDepth = new Integer(defaultBitDepth); }
if (null == frequency) { frequency = new Long(defaultFrequency); }
bitRate = new Integer(bitDepth.intValue() * frequency.intValue());
} else if (null == bitDepth) {
if (null == frequency) { frequency = new Long(defaultFrequency); }
if (null == bitRate) { bitRate = new Integer(defaultBitRate); }
bitDepth = new Integer(bitRate.intValue() / frequency.intValue());
} else if (null == frequency) {
if (null == bitRate) { bitRate = new Integer(defaultBitRate); }
if (null == bitDepth) { bitDepth = new Integer(defaultBitDepth); }
frequency = new Long(bitRate.longValue() / bitDepth.longValue());
}
format = new AudioFormat(format.getContainer(), format.getCodec(), format.isBigEndian(), bitDepth, bitRate, frequency);
}
// Retrun prefered AudioFormat
return format;
}
// Indicates the passed audioFormats is empty or specified no codecs or containers
assert (false);
// Return null indicating failue
return null;
}
protected void setItemRegistry(ItemRegistry itemRegistry) {
this.itemRegistry = itemRegistry;
}