-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bdd9064
commit 84fe32e
Showing
6 changed files
with
340 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package net.oijon.algonquin.tts.trm; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.Arrays; | ||
|
||
import javax.sound.sampled.AudioFileFormat; | ||
import javax.sound.sampled.AudioFormat; | ||
import javax.sound.sampled.AudioInputStream; | ||
import javax.sound.sampled.AudioSystem; | ||
|
||
// Highly experimental. | ||
public class TRM { | ||
|
||
public static void makeTestSound() throws IOException { | ||
final double sampleRate = 44100.0; | ||
final double frequency = 440; | ||
final double frequency2 = 90; | ||
final double amplitude = 1.0; | ||
final double seconds = 2.0; | ||
final double twoPiF = 2 * Math.PI * frequency; | ||
final double piF = Math.PI * frequency2; | ||
|
||
float[] buffer = new float[(int)(seconds * sampleRate)]; | ||
|
||
for (int sample = 0; sample < buffer.length; sample++) { | ||
double time = sample / sampleRate; | ||
buffer[sample] = (float)(amplitude * Math.cos(piF * time) * Math.sin(twoPiF * time)); | ||
} | ||
|
||
final byte[] byteBuffer = new byte[buffer.length * 2]; | ||
|
||
int bufferIndex = 0; | ||
for (int i = 0; i < byteBuffer.length; i++) { | ||
final int x = (int)(buffer[bufferIndex++] * 32767.0); | ||
|
||
byteBuffer[i++] = (byte)x; | ||
byteBuffer[i] = (byte)(x >>> 8); | ||
} | ||
|
||
|
||
if (new File(System.getProperty("user.home") + "/AlgonquinTTS").exists() == false) { | ||
new File(System.getProperty("user.home") + "/AlgonquinTTS").mkdir(); | ||
} | ||
|
||
File out = new File(System.getProperty("user.home") + "/AlgonquinTTS/out10.wav"); | ||
|
||
final boolean bigEndian = false; | ||
final boolean signed = true; | ||
|
||
final int bits = 16; | ||
final int channels = 1; | ||
|
||
AudioFormat format = new AudioFormat((float)sampleRate, bits, channels, signed, bigEndian); | ||
ByteArrayInputStream bais = new ByteArrayInputStream(byteBuffer); | ||
AudioInputStream audioInputStream = new AudioInputStream(bais, format, buffer.length); | ||
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, out); | ||
audioInputStream.close(); | ||
} | ||
|
||
public static String createTestTube() { | ||
String exception = ""; | ||
Tube testTube = new Tube(17); | ||
Voicebox voiceBox = new Voicebox(5); | ||
|
||
exception += "\nVoicebox wave: "; | ||
|
||
for (int i = 0; i < testTube.getSampleRate()*2; i++) { | ||
exception += voiceBox.frame() + ", "; | ||
} | ||
|
||
exception += ("outwards elements: " + Arrays.toString(testTube.out()) + "\n"); | ||
exception += "Full array: " + "\n"; | ||
for (int i = 0; i < testTube.getSampleRate(); i++) { | ||
exception += testTube.getDelayLine()[i][0] + ", "; | ||
} | ||
exception += "\n"; | ||
|
||
for (int i = 0; i < testTube.getSampleRate(); i++) { | ||
exception += testTube.getDelayLine()[i][1] + ", "; | ||
} | ||
|
||
return exception; | ||
} | ||
|
||
public static String createTestWave() throws IOException { | ||
String exception = ""; | ||
|
||
Voicebox voiceBox = new Voicebox(1); | ||
|
||
final double sampleRate = 44100.0; | ||
final double seconds = 2.0; | ||
|
||
exception += "Sample Rate: " + sampleRate + "\n"; | ||
exception += "Amplitude: 1\n"; | ||
exception += "Seconds: " + seconds + "\n"; | ||
|
||
|
||
float[] buffer = new float[(int)(seconds * sampleRate)]; | ||
|
||
for (int sample = 0; sample < buffer.length; sample++) { | ||
buffer[sample] = voiceBox.frame(); | ||
} | ||
|
||
final byte[] byteBuffer = new byte[buffer.length * 2]; | ||
|
||
int bufferIndex = 0; | ||
for (int i = 0; i < byteBuffer.length; i++) { | ||
final int x = (int)(buffer[bufferIndex++] * 32767.0); | ||
|
||
byteBuffer[i++] = (byte)x; | ||
byteBuffer[i] = (byte)(x >>> 8); | ||
} | ||
|
||
|
||
if (new File(System.getProperty("user.home") + "/AlgonquinTTS").exists() == false) { | ||
new File(System.getProperty("user.home") + "/AlgonquinTTS").mkdir(); | ||
exception += "Created new directory in " + System.getProperty("user.home") + "/AlgonquinTTS" + "\n"; | ||
} | ||
|
||
File out = new File(System.getProperty("user.home") + "/AlgonquinTTS/testwave.wav"); | ||
exception += "Created new file in " + System.getProperty("user.home") + "/AlgonquinTTS/testwave.wav" + "\n"; | ||
|
||
final boolean bigEndian = false; | ||
final boolean signed = true; | ||
|
||
exception += "Big Endian: " + bigEndian + "\n"; | ||
exception += "Signed: " + signed + "\n"; | ||
|
||
final int bits = 16; | ||
final int channels = 1; | ||
|
||
exception += "Bits: " + bits + "\n"; | ||
exception += "Channels: " + channels + "\n"; | ||
|
||
AudioFormat format = new AudioFormat((float)sampleRate, bits, channels, signed, bigEndian); | ||
ByteArrayInputStream bais = new ByteArrayInputStream(byteBuffer); | ||
AudioInputStream audioInputStream = new AudioInputStream(bais, format, buffer.length); | ||
AudioSystem.write(audioInputStream, AudioFileFormat.Type.WAVE, out); | ||
audioInputStream.close(); | ||
|
||
return exception; | ||
} | ||
|
||
public static String createSchwaTubeTest() { | ||
String exception = ""; | ||
|
||
int sampleRate = 2018; // L = c/F, where L is the length (17cm), c is the speed of sound (cm/s), and F is the sampling frequency | ||
float delayLine[][] = new float[sampleRate][2]; | ||
for (int i = 0; i < 2; i++) { | ||
for (int j = 0; j < sampleRate; j++) { | ||
delayLine[j][i] = (delayLine[j-1][i]); | ||
} | ||
} | ||
|
||
return exception; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package net.oijon.algonquin.tts.trm; | ||
|
||
public class Tube { | ||
|
||
private int length; | ||
private int sampleRate; | ||
private final int speedOfSound = 34300; //in cm/s | ||
private double loss = 0.97; //3% loss | ||
private float[][] delayLine; | ||
|
||
public Tube (int length) { | ||
this.length = length; | ||
// L = c/F, where L is the length (17cm), c is the speed of sound (cm/s), and F is the sampling frequency | ||
sampleRate = speedOfSound/this.length; | ||
//Creates the delay array based off | ||
delayLine = new float[sampleRate][2]; | ||
} | ||
|
||
//create and manage a delay line | ||
//returns false if there is still room before sound makes its way out | ||
//returns true if its pushing the sound out to the next tube | ||
//this is done by checking if the last part of the array for the sample rate is filled. | ||
public boolean push(float pushAmount) { | ||
for (int i = 0; i < sampleRate-1; i++) { | ||
delayLine[i+1][0] = delayLine[i][0]; | ||
} | ||
delayLine[0][0] = pushAmount; | ||
delayLine[sampleRate-1][1] = -1*delayLine[sampleRate-1][0]; | ||
for (int i = sampleRate-1; i > 0; i--) { | ||
delayLine[i-1][0] = delayLine[i][0]; | ||
} | ||
if (Float.isNaN(delayLine[sampleRate-1][0])) { | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
} | ||
|
||
//convert to 44.1 kHz by adding new data to follow the slope. | ||
//i could very well be misunderstanding something about this in the paper by Manzara | ||
//if so, this method will probably be replaced. | ||
public float[][] standardize() { | ||
float[][] standard = new float[44100][2]; | ||
int multiple = (int)(44100/sampleRate); | ||
for (int h = 0; h < 2; h++) { | ||
for (int i = 0; i < sampleRate; i++) { | ||
float slope = 1; | ||
if (i+1 < sampleRate) { | ||
slope = (delayLine[i+1][h]-delayLine[i][h])/((i+1)-i); | ||
} else { | ||
slope = (delayLine[sampleRate-1][h]-delayLine[i][h])/((sampleRate-1)-i); | ||
} | ||
for (int j = 0; j < multiple; j++) { | ||
//could be optimized more | ||
if (j == 0) { | ||
standard[i*multiple][h] = delayLine[i][h]; | ||
} else { | ||
standard[j][h] = standard[j-1][h]*slope; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return standard; | ||
} | ||
|
||
public float[] out() { | ||
float[] out = new float[2]; | ||
out[0] = delayLine[sampleRate-1][0]; | ||
out[1] = delayLine[sampleRate-1][1]; | ||
return out; | ||
} | ||
|
||
//debug only, should not be used in production | ||
public float[][] getDelayLine() { | ||
return delayLine; | ||
} | ||
public int getLength() { | ||
return length; | ||
} | ||
public int getSampleRate() { | ||
return sampleRate; | ||
} | ||
public double getLoss() { | ||
return loss; | ||
} | ||
public void setLoss(double loss) { | ||
this.loss = loss; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package net.oijon.algonquin.tts.trm; | ||
|
||
public class Voicebox { | ||
|
||
private float intensity; | ||
private int frameCount = 0; | ||
|
||
public Voicebox(float intensity) { | ||
this.intensity = intensity; | ||
} | ||
public float frame() { | ||
float amount = (float) ((Math.sin(frameCount*(float)(1F/8F)))*intensity); | ||
frameCount++; | ||
return amount; | ||
} | ||
public int getFrameCount() { | ||
return frameCount; | ||
} | ||
public float getIntensity() { | ||
return intensity; | ||
} | ||
public void setIntensity(float intensity) { | ||
this.intensity = intensity; | ||
} | ||
|
||
} |