I have a JavaSoundRecorder that I have created as shown below. When I create an object of the class and call the finish() function the line does not stop/close and remains active (does not reach null state). Meaning that I can only make a single recording with the recorder. What can I do to fix this issue?
import java.io.*;
import javax.sound.sampled.*;
import java.util.Set;
public class JavaSoundRecorder {
private TargetDataLine line;
private AudioFileFormat.Type fileType;
private File savedWav;
private AudioFormat audioForm;
private DataLine.Info info;
public int errorNum;
public void setFile(File savedWav) {
this.savedWav = savedWav;
}
/*constructs class*/
public JavaSoundRecorder() {
fileType = AudioFileFormat.Type.WAVE;
audioForm = getAudioFormat();
info = new DataLine.Info(TargetDataLine.class, audioForm);
}
/*
* Defines an audio format
*/
AudioFormat getAudioFormat() {
float sampleRate = 16000;
int sampleSizeInBits = 16;
int channels = 1;
boolean signed = true;
boolean BigEndian = true;
AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits, channels , signed, BigEndian);
return format;
}
/*Captures the sound and records in WAV fiLE, creates a new thread for recording*/
protected int startRecording(String path) {
setFile(new File(path));
errorNum = 0;
if(line == null) {
Thread thread2 = new Thread(new Runnable() {
#Override
public void run() {
try {
//check if system supports the data line
if(!AudioSystem.isLineSupported(info)) {
System.out.println("not supported")
}
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(audioForm);
line.start();
AudioInputStream ais = new AudioInputStream(line);
//write recoding to file..
AudioSystem.write(ais, fileType, savedWav);
}
catch(LineUnavailableException e) {
errorNum = 3;
e.printStackTrace();
}
catch(IOException e) {
errorNum = 4;
e.printStackTrace();
}
}
});
thread2.start();
}
return errorNum;
}
/*stops recording*/
public void finish() {
line.stop();
line.close();
}
}
I'd look at using loose coupling pattern. The finish() method should suggest to the recording thread to do the work of closing and cleaning up, not actually do that work itself. Thus have finish() flip a boolean named something like isRunning to false. The boolean can be volatile to help ensure the change in value is immediately read across the different threads.
With this, move the code which closes and cleans up to the end of the run() method, and surround the code that executes the write() with a while(isRunning) block.
Now, I'm not up enough on the details to know off the top of my head the exact changes required, but I think you will also have to refactor a bit so the writing is an action that repeats, that repeatedly gives control back to the enclosing while() after each write operation.
Related
I am attempting to use the TARSOS DSP library to extract the MFCC values from wav files, before using DTW to calculate the distance between them.
Unfortunately I am having trouble undesrtanding how the code from the MFCC class can be used on a wav file.
I am unsure If I need to convert the wav file into some sort of array buffer first.
Please see the code from the library for the MFCC class at this link.
https://github.com/JorenSix/TarsosDSP/blob/master/src/core/be/tarsos/dsp/mfcc/MFCC.java
If I could get advice about how to properly use this code to get MFCC values from a wav file, or perhaps reccomendattions about another method, I would greatly appreciate it.
This is sample code should do the job for small files. It loads the whole .wav file into a byte array so this is not right approach for big files. The final variables should probably be changed according to your use case. I'm still new to java so there's no guarantee that this is the best approach.
public class App {
private final static String pathToFile = "D:\\TarsosWavTest\\wavs\\1000HzTone.wav";
private final static int audioBufferSize = 2048;
private final static int bufferOverlap = 1024;
private final static int amountOfMelFilters = 20;
private final static int amountOfCepstrumCoef = 30;
private final static float lowerFilterFreq = 133.33f;
private final static float upperFilterFreq = 8000f;
public static void main(String[] args) {
File file = new File(pathToFile);
AudioInputStream audioInputStream;
byte[] byteAudioArray;
AudioDispatcher audioDispatcher;
try {
audioInputStream = AudioSystem.getAudioInputStream(file);
byteAudioArray = audioInputStream.readAllBytes();
} catch (Exception e) {
System.out.println("Exception occured");
e.printStackTrace();
return;
}
try {
audioDispatcher = AudioDispatcherFactory.fromByteArray(byteAudioArray, audioInputStream.getFormat(),
audioBufferSize, bufferOverlap);
} catch (Exception e) {
e.printStackTrace();
return;
}
final MFCC mfccProcessor = new MFCC(audioBufferSize, audioInputStream.getFormat().getSampleRate(),
amountOfCepstrumCoef, amountOfMelFilters, lowerFilterFreq, upperFilterFreq);
audioDispatcher.addAudioProcessor(mfccProcessor);
audioDispatcher.addAudioProcessor(new AudioProcessor() {
#Override // gets called on each audio frame
public boolean process(AudioEvent audioEvent) {
float[] mfccs = mfccProcessor.getMFCC();
/* do whatever necessary with the mfcc elements here
e.g print them */
//System.out.println(Arrays.toString(mfccs));
return true;
}
#Override // gets called when end of the audio file was reached
public void processingFinished() {
System.out.println("end of file reached");
}
});
audioDispatcher.run();// starts a new thread
}}
Please note that different libraries(e.g. librosa) are NOT guaranteed to compute the same MFCCs even with the same input parameters.
So I have 3 threads,
A thread which downloads audio and the audio schedule object from the internet.
A thread which plays the audio according to the audio schedule.
And a web socket "notification" listener that listens for messages that say we have to download new audio and schedule as our current one is outdated.
The program flow is as follows:
On application startup: The ScheduleDownloader starts,downloads audio and schedule file.Once completed it needs to tell the audio player "hey the files are ready and here is the schedule" and it doesnt need to do anything for now
The audio player starts and continuously loops with no exit condition.
The web socket listener starts,when it gets a message.It should tell the schedule downloader "You need to start again as there is new files you need to download",it doesnt need to send any data to the schedule downloaded,just start it up again.The music should remain playing.Once it is done it should now restart the audio player thread with the new schedule.
Here is what I have so far,I am not sure how to get ScheduleDownloader to tell AudioPlayer "the files are ready and you need to start,here is the schedule" or "you need to restart with the new schedule,here it is" or how to get the listener to say "ScheduleDownloader you need to start again"
public class ScheduleDownloader extends Thread {
private Thread t;
private String threadName;
String username;
String password;
public ScheduleDownloader(String username,String password,String threadName){
this.username = username;
this.password = password;
this.threadName= threadName;
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}}
public void run() {
try {
Schedule schedule= null;
while(schedule == null){
System.out.println("Searching for schedule");
schedule= getTodaysSchedule();
}
System.out.println("Schedule Found");
boolean result = false;
while(result == false){
result = downloadFiles(schedule);
}
System.out.println("Files Downloaded");
} catch (IOException e) {
e.printStackTrace();
}
}
public Schedule getTodaysSchedule() throws IOException {
Schedule schedule = null;
CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials
= new UsernamePasswordCredentials(username,password);
provider.setCredentials(AuthScope.ANY, credentials);
String url = "http://localhost:5000/api/schedule/today";
HttpClient httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(provider).build(); //Use this instead
HttpGet request = new HttpGet(url);
HttpResponse response = httpClient.execute(request);
//read content response body
if (response.getStatusLine().getStatusCode() != 200) {
System.out.println("sorry error:" + response.getStatusLine().getStatusCode());
} else {
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
//change json response to java objects
Gson gson = new Gson();
schedule = gson.fromJson(String.valueOf(result),Schedule.class);
}
return schedule;
}
public static boolean downloadFiles(Schedule schedule) {
//get the music
for(int i =0;i<schedule.getMusicScheduleItems().size();i++){
downloadOneFile("shoutloudaudio","music/" +
schedule.getMusicScheduleItems().get(i).getMusic().getId()+
"-music.wav");
}
//get the advertisements
for(int i =0;i<schedule.getAdvertisementScheduleItems().size();i++){
downloadOneFile("shoutloudaudio","advertisements/" +
schedule.getAdvertisementScheduleItems().get(i).getAdvertisement().getId()+
"-advertisement.wav");
}
return true;
}
public static boolean downloadOneFile(String bucketName,String key) {
if( new File(key.split("/")[1]).isFile()){
//check if we have it already and dont need to download it
System.out.println(key + " alraeady exits");
return true;
}
AWSCredentials awsCredentials = new BasicAWSCredentials(
"removed",
"removed"
);
AmazonS3 s3client = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(Regions.EU_WEST_1)
.build();
S3Object s3object = s3client.getObject(bucketName, key);
S3ObjectInputStream inputStream = s3object.getObjectContent();
InputStream reader = new BufferedInputStream(
inputStream);
File file = new File(key.split("/")[1]);//save the file as whats after the / in key
OutputStream writer = null;
try {
writer = new BufferedOutputStream(new FileOutputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
int read = -1;
try {
while ((read = reader.read()) != -1) {
writer.write(read);
}
writer.flush();
writer.close();
}catch(IOException e){
e.printStackTrace();
return false;
}
return true;
}
}
AudioPlayer
public class AudioPlayer extends Thread {
Long currentFrameMusic;
Long currentFrameAdvertisement;
Clip clipMusic;
Clip clipAdvertisement;
private Thread t;
// current status of clip
String statusMusic;
String statusAdvertisement;
static AudioInputStream musicInputStream;
static AudioInputStream advertisementInputStream;
static String filePath;
Schedule schedule;
// constructor to initialize streams and clip
public AudioPlayer(Schedule schedule)
throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
//setup audio stream for music first
// create AudioInputStream object
this.schedule = schedule;
appendMusicFiles(schedule);
// create clip reference
clipMusic = AudioSystem.getClip();
// open audioInputStream to the clip
clipMusic.open(musicInputStream);
clipMusic.loop(Clip.LOOP_CONTINUOUSLY);
}
public void run(){
playMusic();
try {
checkShouldWePlayAnAdvertisement();
} catch (IOException e) {
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void start(){
t = new Thread (this, "AudioPlayerThread");
t.start ();
}
public void start2() throws IOException, UnsupportedAudioFileException, LineUnavailableException, InterruptedException {
playMusic();
checkShouldWePlayAnAdvertisement();
}
public void playMusic()
{
//start the clip
clipMusic.start();
statusMusic = "play";
}
// Method to pause the audio
public void pauseMusic()
{
if (statusMusic.equals("paused"))
{
System.out.println("audio is already paused");
return;
}
this.currentFrameMusic =
this.clipMusic.getMicrosecondPosition();
clipMusic.stop();
statusMusic = "paused";
System.out.println("pausing music");
}
// Method to resume the audio
public void resumeAudioMusic() throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
if (statusMusic.equals("play"))
{
System.out.println("Audio is already "+
"being played");
return;
}
clipMusic.close();
resetAudioStreamMusic();
clipMusic.setMicrosecondPosition(currentFrameMusic);
System.out.println("resuming music");
this.playMusic();
}
// Method to restart the audio
public void restartMusic() throws IOException, LineUnavailableException,
UnsupportedAudioFileException
{
clipMusic.stop();
clipMusic.close();
resetAudioStreamMusic();
currentFrameMusic = 0L;
clipMusic.setMicrosecondPosition(0);
this.playMusic();
}
// Method to stop the audio
public void stopMusic() throws UnsupportedAudioFileException,
IOException, LineUnavailableException
{
currentFrameMusic = 0L;
clipMusic.stop();
clipMusic.close();
}
public void resetAudioStreamMusic() throws UnsupportedAudioFileException, IOException,
LineUnavailableException
{
clipMusic = AudioSystem.getClip();
appendMusicFiles(schedule);
// open audioInputStream to the clip
clipMusic.open(musicInputStream);
clipMusic.loop(Clip.LOOP_CONTINUOUSLY);
}
public static void appendMusicFiles(Schedule schedule) throws IOException, UnsupportedAudioFileException {
//add the first audio file to stream
AudioInputStream appendedFiles = AudioSystem.getAudioInputStream(
new File(schedule.getMusicScheduleItems().get(0).getMusic()
.getId() + "-music.wav"));
//loop through an combine
for(int i =1;i<schedule.getMusicScheduleItems().size();i++){
File file= new File(schedule.getMusicScheduleItems().get(i).getMusic()
.getId() + "-music.wav");
AudioInputStream toBeAppended = AudioSystem.getAudioInputStream(file);
//append them
appendedFiles =
new AudioInputStream(
new SequenceInputStream(appendedFiles, toBeAppended),
appendedFiles.getFormat(),
appendedFiles.getFrameLength() + toBeAppended.getFrameLength());
}
musicInputStream = appendedFiles;
}
//advertisement methods
public void playAdvertisements() throws LineUnavailableException, IOException, InterruptedException {
clipAdvertisement = AudioSystem.getClip();
// open audioInputStream to the clip
clipAdvertisement.open(advertisementInputStream);
System.out.println(clipAdvertisement.getMicrosecondLength());
//start the clip
clipAdvertisement.start();
Thread.sleep(clipAdvertisement.getMicrosecondLength() / 1000);
statusAdvertisement = "play";
System.out.println("playing advertisements");
}
// Method to pause the audio
public void pauseAdvertisements()
{
if (statusAdvertisement.equals("paused"))
{
System.out.println("audio is already paused");
return;
}
this.currentFrameAdvertisement =
this.clipAdvertisement.getMicrosecondPosition();
clipAdvertisement.stop();
statusAdvertisement = "paused";
}
// Method to resume the audio
public void resumeAudioAdvertisement() throws UnsupportedAudioFileException,
IOException, LineUnavailableException, InterruptedException {
if (statusAdvertisement.equals("play"))
{
System.out.println("Audio is already "+
"being played");
return;
}
clipAdvertisement.close();
resetAudioStreamAdvertisement();
clipAdvertisement.setMicrosecondPosition(currentFrameMusic);
this.playAdvertisements();
}
// Method to restart the audio
public void restartAdvertisement() throws IOException, LineUnavailableException,
UnsupportedAudioFileException, InterruptedException {
clipAdvertisement.stop();
clipAdvertisement.close();
resetAudioStreamAdvertisement();
currentFrameAdvertisement = 0L;
clipAdvertisement.setMicrosecondPosition(0);
this.playAdvertisements();
}
// Method to stop the audio
public void stopAdvertisement() throws UnsupportedAudioFileException,
IOException, LineUnavailableException, InterruptedException {
currentFrameAdvertisement = 0L;
clipAdvertisement.stop();
clipAdvertisement.close();
System.out.println("stopping advertisement");
}
public void resetAudioStreamAdvertisement() throws UnsupportedAudioFileException, IOException,
LineUnavailableException
{
advertisementInputStream = AudioSystem.getAudioInputStream(
new File(filePath).getAbsoluteFile());
clipAdvertisement.open(musicInputStream);
clipAdvertisement.loop(Clip.LOOP_CONTINUOUSLY);
}
public static void appendAdvertisementFiles(List<Advertisement> advertisementItems) throws IOException, UnsupportedAudioFileException {
//add the first audio file to stream
AudioInputStream appendedFiles = AudioSystem.getAudioInputStream(
new File(advertisementItems.get(0)
.getId() + "-advertisement.wav"));
//loop through an combine
for(int i =1;i<advertisementItems.size();i++){
File file= new File(advertisementItems.get(i)
.getId() + "-advertisement.wav");
AudioInputStream toBeAppended = AudioSystem.getAudioInputStream(file);
//append them
appendedFiles =
new AudioInputStream(
new SequenceInputStream(appendedFiles, toBeAppended),
appendedFiles.getFormat(),
appendedFiles.getFrameLength() + toBeAppended.getFrameLength());
}
advertisementInputStream = appendedFiles;
}
public void checkShouldWePlayAnAdvertisement() throws IOException, UnsupportedAudioFileException, LineUnavailableException, InterruptedException {
ArrayList<String> playedAtTimes = new ArrayList<>();
ArrayList<Advertisement> advertisementsToBePlayed = new ArrayList<>();
boolean found;
//played at times is used to keep track of what time we played advertisements
//so when the loop reruns and the time hasnt changed it doesnt play it again
while(true){
found = false;
ZonedDateTime zdt = ZonedDateTime.now();
String timeHHMM =zdt.toString().substring(11,16);
for(int i =0;i<schedule.getAdvertisementScheduleItems().size();i++)
{
if(schedule.getAdvertisementScheduleItems().get(i).getTimes()
.contains(timeHHMM))
{
//this item should be played now
if(playedAtTimes.contains(timeHHMM)){
//we already played this,but the time hasnt changed when the loop ran again
}else{
advertisementsToBePlayed.add(schedule.getAdvertisementScheduleItems().get(i).getAdvertisement());
found = true;
}
}
}
if(found== true){
playedAtTimes.add(timeHHMM);
appendAdvertisementFiles(advertisementsToBePlayed);
pauseMusic();
playAdvertisements();
stopAdvertisement();
resumeAudioMusic();
}
}
}
}
IotClient(part of listener)
public class IotClient extends Thread {
Thread t;
String username;
public IotClient(String username) {
this.username = username;
}
public void run(){
String clientEndpoint = "removve"; // replace <prefix> and <region> with your own
String clientId = "1"; // replace with your own client ID. Use unique client IDs for concurrent connections.
// AWS IAM credentials could be retrieved from AWS Cognito, STS, or other secure sources
AWSIotMqttClient client = new AWSIotMqttClient(clientEndpoint, clientId, "remove", "remove");
// optional parameters can be set before connect()
try {
client.connect();
} catch (AWSIotException e) {
e.printStackTrace();
}
AWSIotQos qos = AWSIotQos.QOS0;
AWSIotTopic topic = new MyTopic("schedule/"+ username, qos);
try {
client.subscribe(topic, true);
} catch (AWSIotException e) {
e.printStackTrace();
}
while(true){
}
}
public void start(){
if (t == null) {
t = new Thread (this, "IotClientThread");
t.start ();
}
}
MyTopic(part of listener)
public class MyTopic extends AWSIotTopic {
public MyTopic(String topic, AWSIotQos qos) {
super(topic, qos);
}
#Override
public void onMessage(AWSIotMessage message) {
System.out.println("Message recieved from topic: "+ message.getStringPayload());
}
}
Threads communicate via shared references to messages 'containers' objects in memory. That could be as simple as mere mutable field of a shared instance of some class, or more typical collection like list, map, but especially queues.
ArrayBlockingQueue is a good shared reference. There would be a queue for each message direction from one thread to another. If you had 3 threads that could truly talks to each other, you would have 3 pairs, thus 6 queues (2 for each pair). However, it is often the case that messages flow only in one direction, so you might save a few.
Now, the core of these communications is a mechanism to wait for some message (reader/consumer), and notify when a message is pushed (writer/producer).
Of course, you can learn (penty of tutorials out there) from the bottom going up, from the primitive wait/notify, or you can jump into classes like ArrayBlockingQueue which abstract the wait/notify of messages into take()/put(). I recommend starting from the bottom as things will make sense more rapidly when you meet other classes in java.util.concurrent.*
I cannot give you code, it would be largely not understandable at your level without having learned the basic of ITC (inter-thread communications).
Good learning!
PS: there are many pitfalls on the way, like thread safety, atomicity of writes, lock free algorithms, deadlocks, livelocks, starvation. Just the multi queue example above can lead to circular dependencies on message arrival, particularly when queue get full and block. This is a science!
My problem is that the web service returns a value of the static variable response in the recognition class before the thread updates its value (not up to date value)
here is my web service :
#GET
#Produces("application/json")
public synchronized String returnTitle() {
String result="init value";
Recognition recognition = new Recognition();
FutureTask<String> future = new FutureTask(recognition);
future.run();
System.out.println("result0 = "+result);
try{
System.out.println("result = "+result);
result = future.get();
System.out.println("result1 = "+result);
}catch (Exception e){e.printStackTrace();}
return "<h1>hello</h1> "+ Recognition.response;
}
This class contains the static variable called response that well be returned by the web service.
import java.io.File;
import java.util.List;
import java.util.concurrent.Callable;
import com.bitsinharmony.recognito.MatchResult;
public class Recognition implements Callable<String>{
public static String response =""; // The variable to return by the web service.
#Override
public String call() throws Exception {
response= "";
if (!Ressources.isInitilalized){ // if the initialization of training data is not done yet.
Ressources.init(); // initialize training data
Ressources.isInitilalized= true; //changing the boolean variable to know that inisialization has been done next execution
}
final JavaSoundRecorder recorder = new JavaSoundRecorder(); // Class used to record voice from microphone and save it to .wav file.
Thread stopper = new Thread(new Runnable() { // Thread that sleeps 5000 ms then stops recording.
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
recorder.finish(); // after timer finished stop recording
try{
File file20 = new File("C:\\RecordAudio.wav");
List<MatchResult<String>> matches = Ressources.recognito.identify(file20);
MatchResult<String> match = matches.get(0);
//file20.delete();
System.out.println(match.getKey() + " " + match.getLikelihoodRatio());
response = match.getKey()+" "+match.getLikelihoodRatio()+"\n";// say for which user the sound recorded belongs with witch probability.
}catch (Exception e){}
}
});
stopper.start(); // start the thread
// start recording
recorder.start(); // start recording
return response;
}
}
This class contains static resources to train the model of speaker identification :
import java.io.File;
import com.bitsinharmony.recognito.Recognito;
public class Ressources {
public static String response = "hello : ";
public final static File file0 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\silence12.wav");
public final static File file00 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\noise12.wav");
public final static File file1 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\dhia12.wav");
public final static File file30 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\dhia30.wav");
public final static File file2 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\dhia2.wav");
public final static File file3 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\obama1.wav");
public final static File file4 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\obama2.wav");
public final static File file5 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\obama3.wav");
public final static File file6 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\reagan1.wav");
public final static File file7 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\reagan2.wav");
public final static File file8 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\reagan3.wav");
public final static File file9 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\georgebush1.wav");
public final static File file10 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\georgebush2.wav");
public final static File file11 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\georgebush3.wav");
public final static File file12 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\georgebush4.wav");
public final static File file13 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\carter1.wav");
public final static File file14 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\carter2.wav");
public final static File file15 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\clinton1.wav");
public final static File file16 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\clinton2.wav");
public final static File file17 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\huyan1.wav");
public final static File file18 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\huyan2.wav");
public final static File file19 = new File("C:\\Users\\dsghaier\\Desktop\\Records\\huyan3.wav");
public static Recognito<String> recognito = new Recognito<String>(16000.0f);
public static boolean isInitilalized = false;
public static void init(){
try{
recognito.createVoicePrint("Dhia", file1);
//recognito.mergeVoiceSample("Dhia", file2);
//recognito.mergeVoiceSample("Dhia", file30);
recognito.createVoicePrint("Obama", file3);
//recognito.mergeVoiceSample("Obama", file4);
//recognito.mergeVoiceSample("Obama", file5);
recognito.createVoicePrint("Reagan", file6);
//recognito.mergeVoiceSample("Reagan", file7);
//recognito.mergeVoiceSample("Reagan", file8);
recognito.createVoicePrint("George Bush", file9);
//recognito.mergeVoiceSample("George Bush", file10);
//recognito.mergeVoiceSample("George Bush", file11);
//recognito.mergeVoiceSample("George Bush", file12);
recognito.createVoicePrint("Carter", file13);
//recognito.mergeVoiceSample("Carter", file14);
//recognito.createVoicePrint("Clinton", file15);
//recognito.mergeVoiceSample("Clinton", file16);
//recognito.createVoicePrint("Huyan", file17);
//recognito.mergeVoiceSample("Huyan", file18);
//recognito.mergeVoiceSample("Huyan", file19);
//recognito.createVoicePrint("Silence", file0);
//recognito.createVoicePrint("Noise", file00);
// ********************************
}catch (Exception e){e.printStackTrace();}
isInitilalized = true;
}
}
And finally this class is used to record sound and save it into a .wav file :
import javax.sound.sampled.*;
import java.io.*;
/**
* A sample program is to demonstrate how to record sound in Java
* author: www.codejava.net
*/
public class JavaSoundRecorder {
// record duration, in milliseconds
static final long RECORD_TIME = 500;
// path of the wav file
File wavFile = new File("C:/RecordAudio.wav");
// format of audio file
AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
// the line from which audio data is captured
TargetDataLine line;
/**
* Defines an audio format
*/
AudioFormat getAudioFormat() {
float sampleRate = 16000;
int sampleSizeInBits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = true;
AudioFormat format = new AudioFormat(sampleRate, sampleSizeInBits,
channels, signed, bigEndian);
return format;
}
/**
* Captures the sound and record into a WAV file
*/
public void start() {
try {
AudioFormat format = getAudioFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
// checks if system supports the data line
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Line not supported");
System.exit(0);
}
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start(); // start capturing
// System.out.println("Start capturing...");
AudioInputStream ais = new AudioInputStream(line);
// System.out.println("Start recording...");
// start recording
AudioSystem.write(ais, fileType, wavFile);
} catch (LineUnavailableException ex) {
ex.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
/**
* Closes the target data line to finish capturing and recording
*/
public void finish() {
line.stop();
line.close();
// System.out.println("Finished");
}
}
Maybe you should just initialize your static variable.
Initializing and declaring a variable is not the same:
Initializing : int a = 0;
Declaring : int a;
If this is not what you are looking for, maybe you might be a bit more specific and show us an error message
I am having a problem wit AudioRecord.
I am developing an application that needs to record some an impulse response from the MIC and make some DSP with it.
The audio captured is stored in a WAV file and being plotted afterwards from this file.
I´ve created a class called GrabaAudio which is expected to record a wav file of 3 sec long.
The problem is that I am obtaining ramdonly either wav files of 3 sec and 1,5 sec without a clear reason.
This is what I am supossed to obtain always:
Waveform:
But actually, that result is just obtained sometimes, while most of the time this is what I obtain:
What is really curious about this is that, when I obtain the expected result in the plot, I play the wav file to see what has actually been recorded and I can hear the impulse, but just for 1,5 sec instead of 3. Therefore the samples obtained are half of the expected.
On the other hand, when I obtain the plot with the duplicated impulse, the number of samples is the expected and the wav duration is 3 sec, but I don´t know why the impulse appears twice.
Do you guys know what am I doing wrong?
Here´s the relevant part of the code:
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#SuppressLint("NewApi")
public class GrabaAudio {
private static final int RECORDER_BPP = 16;
private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
public int RECORDER_SAMPLERATE = 8000;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private AudioRecord recorder = null;
private int bufferSize = 0;
private Thread recordingThread = null;
public boolean isRecording = false;
public boolean triggered=false, processed=false;
int bufferTotal=0, read=0, indice=0, indice2=0;
byte[] circBuffer=new byte[8192*3];//AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
//RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING)*3
AutomaticGainControl agc;
File file= new File(getFilename());
CircularArrayList<Byte> circ= new CircularArrayList ((AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING))/2);
int circCapacity=circ.capacity();
Main main;
public GrabaAudio(){
bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING);
if (bufferSize <8192){
bufferSize=8192;
}
//boolean tiene=agc.getEnabled();
}
public void startRecording(){
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize*6);
agc = AutomaticGainControl.create(recorder.getAudioSessionId());
final boolean agc2=agc.isAvailable();
int i = recorder.getState();
if(i==1)
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
writeAudioDataToFile();
}
},"AudioRecorder Thread");
recordingThread.start();
}
public void writeAudioDataToFile(){
byte data[] = new byte[6*bufferSize];
byte arrayBytes[]= new byte [3*bufferSize];
String filename = getTempFilename();
FileOutputStream os = null;
try {
os = new FileOutputStream(filename);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(null != os){
while(isRecording){
read = recorder.read(data, 0, 6*bufferSize);
//**************************************
arrayBytes=calculateImpulseLevel(data);
if(AudioRecord.ERROR_INVALID_OPERATION != read && indice>=(bufferSize*3-3) ){
try {
os.write(arrayBytes);
processed=true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private byte[] calculateImpulseLevel(byte[] array){
double[] arraySamples=new double[array.length/2];
for (int i=0,j=0; i<=array.length-2 ;i+=2){
double sampleAmpl=(double)Math.abs((array[i+1] << 8 | array[i] & 0xff)/32767.0);
if (sampleAmpl<0.3 && !triggered){
int s=circ.size();
if (s<circCapacity){
circ.add(array[i]);
circ.add(array[i+1]);
} else {
circ.remove(0);
circ.add(array[i]);
circ.remove(0);
circ.add(array[i+1]);
}
} else{
if(!triggered){
triggered=true;
} indice=indice2+(bufferSize/2);
if (indice>3*bufferSize-2){
i=array.length;
}else{
circBuffer[indice]=array[i];
circBuffer[indice+1]=array[i+1];
indice2+=2;
arraySamples[j]=sampleAmpl;
}
}}
System.arraycopy(toByteArray(circ),0,circBuffer,0,circ.size());
return circBuffer;
}
I have had problems with AudioRecord returning repeated data in a sequence of reads, resolved by changing the size of the AudioRecord buffer so as not to be an exact multiple of the audiodata buffer size e.g., try:
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize*9);
Also are you sure that the writes are always able to keep up with the reads? I would insert some log statements to check the timings. You may need to copy the read data in memory and write in another thread.
This question already has answers here:
Threads and file writing
(6 answers)
Closed 9 years ago.
i have 20 threads that write with the println() function on a file called results.txt. How can i synchronize them all?
I note every time my program run i have different number of lines of text in results.txt.
Thank you.
Access the file through a class that contains a synchronized method to write to the file. Only one thread at a time will be able to execute the method.
I think that Singleton pattern would fit for your problem:
package com.test.singleton;
public class Singleton {
private static final Singleton inst= new Singleton();
private Singleton() {
super();
}
public synchronized void writeToFile(String str) {
// Do whatever
}
public static Singleton getInstance() {
return inst;
}
}
Every time you need to write to your file, you only would have to call:
Singleton.getInstance().writeToFile("Hello!!");
Duplicate question ... duplicate answer. As I said here:
If you can hold your file as a FileOutputStream you can lock it like this:
FileOutputStream file = ...
....
// Thread safe version.
void write(byte[] bytes) {
try {
boolean written = false;
do {
try {
// Lock it!
FileLock lock = file.getChannel().lock();
try {
// Write the bytes.
file.write(bytes);
written = true;
} finally {
// Release the lock.
lock.release();
}
} catch ( OverlappingFileLockException ofle ) {
try {
// Wait a bit
Thread.sleep(0);
} catch (InterruptedException ex) {
throw new InterruptedIOException ("Interrupted waiting for a file lock.");
}
}
} while (!written);
} catch (IOException ex) {
log.warn("Failed to lock " + fileName, ex);
}
}
You are intend to write data into one file. So if you try to lock the whole file, it'd better to use a single thread to do this job. Although you spawn 20 threads, but there is only one of them is running every time you call the method, the others are just waiting for the lock.
I recommend you use RandomAccessFile to write data to your file. Then each thread can write some unique data into to the file without locking the whole file.
Some demo code as following
try {
final RandomAccessFile file = new RandomAccessFile("/path/to/your/result.txt", "rw");
final int numberOfThread = 20;
final int bufferSize = 512;
ExecutorService pool = Executors.newFixedThreadPool(numberOfThread);
final AtomicInteger byteCounter = new AtomicInteger(0);
final byte[] yourText = "Your data".getBytes();
for (int i = 0; i < yourText.length; i++) {
pool.submit(new Runnable() {
#Override
public void run() {
int start = byteCounter.getAndAdd(bufferSize);
int chunkSize = bufferSize;
if (start + bufferSize > yourText.length) {
chunkSize = yourText.length - start;
}
byte[] chunkData = new byte[chunkSize];
System.arraycopy(yourText, start, chunkData, 0, chunkSize);
try {
file.write(chunkData);
} catch (IOException e) {
//exception handle
}
}
});
}
file.close();
} catch (Exception e) {
//clean up
}