Archive

Posts Tagged ‘TTS’

Implementing a simple stream based XML Parser

October 18, 2009 Leave a comment

The Wiktionary XML dump -> db is virtually sorted, and was fairly trivial to code, albeit comparatively slow to process (3 mins +/- on my naff laptop to get a full list of available titles, for example, although this also includes a lot of metapages e.g. categories etc). Setup was straightforward enough, one block of code to create the InputStream & instance the methods class, and then the methods class itself.

try {
 InputStream in = new FileInputStream("F:/wiktionary/enwiktionary/wiktionary.xml");
 XMLInputFactory factory = XMLInputFactory.newInstance();
 XMLStreamReader parser = factory.createXMLStreamReader(in);
// instance the custom xml examiner class which contains whatever methods needed...
 XMLStreamMethods xsm = new XMLStreamMethods();
// call required methods
 xsm.examine(parser);
}
catch(Exception e){e.printStackTrace();}

The XMLStreamMethods class (which probably needs a better name!) was largely scarfed and adapted from code from XML.com. I’ll probably get discursive about the methods once this is closer to a decent cut, but effectively I’m really only interested in title and text tag contents, and most of the processing work is in grabbing the IPA renditions from the volumes of surrounding text fluff. Suffice it all that was really required from the example xml.com source was to hack the tag names from headers to title and text and then call workers accordingly.

Advertisements
Categories: Java Tags: , , ,

Wiktionary dump XML content to schema in > 2 minutes

October 3, 2009 Leave a comment

I am still playing with Wiktionary IPA as a source for my implementation of TTS. Conrad Irwin suggested the dump download from Wiktionary might be more appropriate & complete than spidering on demand and building a local map that way, and I could not but agree with him, the Wiki dumps had completely slipped my mind when wrangling with the miscellaneous other little subtasks that this project seems to be engendering.

Anyway, with the downloaded XML weighing in at 120MB+ it looked like this was going to be a nightmare, then I remembered James Clark’s trang, a tool I haven’t used in a long time, just unzip and classpath the executable jar and run as follows:

$ java -jar trang.jar -I xml -O xsd wiktionary_280909.xml /schemas/wiktionary.xsd

& a couple of minutes later, viola (sic).

The output schema looks like this in case you ever need it:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:export-0.3="http://www.mediawiki.org/xml/export-0.3/">
  <xs:import namespace="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="xsi.xsd"/>
  <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
  <xs:element name="mediawiki">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="export-0.3:siteinfo"/>
        <xs:element maxOccurs="unbounded" ref="export-0.3:page"/>
      </xs:sequence>
      <xs:attribute name="version" use="required" type="xs:decimal"/>
      <xs:attribute ref="xsi:schemaLocation" use="required"/>
      <xs:attribute ref="xml:lang" use="required"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="siteinfo">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="export-0.3:sitename"/>
        <xs:element ref="export-0.3:base"/>
        <xs:element ref="export-0.3:generator"/>
        <xs:element ref="export-0.3:case"/>
        <xs:element ref="export-0.3:namespaces"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="sitename" type="xs:NCName"/>
  <xs:element name="base" type="xs:anyURI"/>
  <xs:element name="generator" type="xs:string"/>
  <xs:element name="case" type="xs:NCName"/>
  <xs:element name="namespaces">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="export-0.3:namespace"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="namespace">
    <xs:complexType mixed="true">
      <xs:attribute name="key" use="required" type="xs:integer"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="page">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="export-0.3:title"/>
        <xs:element ref="export-0.3:id"/>
        <xs:element minOccurs="0" ref="export-0.3:redirect"/>
        <xs:element minOccurs="0" ref="export-0.3:restrictions"/>
        <xs:element ref="export-0.3:revision"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="title" type="xs:string"/>
  <xs:element name="redirect">
    <xs:complexType/>
  </xs:element>
  <xs:element name="restrictions" type="xs:string"/>
  <xs:element name="revision">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="export-0.3:id"/>
        <xs:element ref="export-0.3:timestamp"/>
        <xs:element ref="export-0.3:contributor"/>
        <xs:element minOccurs="0" ref="export-0.3:minor"/>
        <xs:element minOccurs="0" ref="export-0.3:comment"/>
        <xs:element ref="export-0.3:text"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="timestamp" type="xs:NMTOKEN"/>
  <xs:element name="contributor">
    <xs:complexType>
      <xs:choice>
        <xs:element ref="export-0.3:ip"/>
        <xs:sequence>
          <xs:element ref="export-0.3:username"/>
          <xs:element ref="export-0.3:id"/>
        </xs:sequence>
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <xs:element name="ip" type="xs:string"/>
  <xs:element name="username" type="xs:string"/>
  <xs:element name="minor">
    <xs:complexType/>
  </xs:element>
  <xs:element name="comment" type="xs:string"/>
  <xs:element name="text">
    <xs:complexType mixed="true">
      <xs:attribute ref="xml:space" use="required"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="id" type="xs:integer"/>
</xs:schema>

That gives me enough to work with, now to tear into the XML with JAXB…..

NB (Later). Well I played with JAXB, but unfortunately there are a number of facets of JAXB which will make this less amenable than XMLBeans, notably the issues surrounding preservation of whitespace & full support for all schema constructs. Close, but unfortunately no cigar on this occasion. So I am now working up an XMLBeans cut, and this is looking promising.

NNB(Later again) Well it looks like XmlBeans won’t play nice with large files, which is a shame because there is a lot of stuff in there that I could have done with. Off to play with STAX /cry….

Categories: Java Tags: , , , , , ,

Implementing Text to Speech quickly with FreeTTS

September 19, 2009 Leave a comment

I had a quick play with the FreeTTS Text to Speech API yesterday. I needed a voice alert for a little Swing app I was running up. Outwardly this looked like hard work, perhaps more work than I cared for, but nevertheless I persisted and came up with this as a quick first shot. I have to do some more work on it to resolve issues with threadedness, but that’s just a matter of time and, like Marcel Proust I will probably get round to it… someday anyway… Let me say that the TTS voices are horrible and work needs doing on these (for which the FreeTTS guys are not responsible) more than the API itself which works pretty much out of the box. The API, when boiled down, does what it says on the label.

You can get FreeTTS from here on Sourceforge.

You need to unzip it, head to the unzipped bin directory and run the JSAPI.exe to make the jars, then put the jars where you need them and make them available to your application. And put the speech.properties file somewhere your app can find it like your {jre}/lib. You will probably end up using the kevin voice. I have it hardcoded but you can easily extend and modify the code to take a String with the name of the voice you want to use or hardcode your own in place of nasty kevin. I’ve put the ShowVoices routine in there to show you the available voices just in case… But kevin works, almost. All you need to do is instantiate TTSReader, and call consume, passing it the String you want it to speak.


import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;

public class TTSReader {

public void showVoices() {
        VoiceManager voiceManager = VoiceManager.getInstance();
        Voice[] v = voiceManager.getVoices();
        for (int i = 0; i > v.length; i++) {
            System.out.println(v[i].getName() + "  : " + v[i].getDomain() );
        }
    }
 
    public void consume(String input)
    {
    VoiceManager voiceManager = VoiceManager.getInstance();
        Voice myVoice = voiceManager.getVoice("kevin");
        myVoice.allocate();
        myVoice.speak(input);
        myVoice.deallocate();
    }
}
Categories: Java Tags: , , , ,