Я пытаюсь создать приложение Java, которое имитирует ввод текста с клавиатуры. Звук нажатия клавиш воспроизводится в al oop (Java выбирает звук нажатия клавиш среди других случайным образом и воспроизводит его) с переменным интервалом (для имитации набора текста реальным человеком).
В начале все работает нормально, но после итерации 95th он прекращает воспроизведение звука (продолжая петлю) менее 4 секунд, а затем воспроизводит звук снова. И после итерации 160th он воспроизводит звук почти каждую секунду (вместо каждой третьей-шестой секунды).
Через некоторое время он перестает воспроизводить звук на долгое время, а затем навсегда .
Вот источник класса AudioPlayer.java
:
package entity;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioPlayer implements Runnable {
private String audioFilePath;
public void setAudioFilePath(String audioFilePath) {
this.audioFilePath = audioFilePath;
}
@Override
public void run() {
File audioFile = new File(audioFilePath);
try {
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
audioClip.start();
boolean playCompleted = false;
while (!playCompleted) {
try {
Thread.sleep(500);
playCompleted = true;
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
audioClip.close();
} catch (UnsupportedAudioFileException ex) {
System.out.println("The specified audio file is not supported.");
ex.printStackTrace();
} catch (LineUnavailableException ex) {
System.out.println("Audio line for playing back is unavailable.");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("Error playing the audio file.");
ex.printStackTrace();
}
}
}
А вот класс Main.java
для проверки имитатора нажатия клавиш:
package sandbox;
import java.util.Random;
import entity.AudioPlayer;
public class Main {
public static void main(String[] args) {
Random rnd = new Random();
AudioPlayer audio;
for(int i = 0; i < 10000; i++) {
int delay = rnd.nextInt(200)+75;
try {
Thread.sleep(delay);
}
catch (InterruptedException ie) {}
int index = rnd.nextInt(3)+1;
audio = new AudioPlayer();
audio.setAudioFilePath("resources/keystroke-0"+index+".wav");
Thread thread = new Thread(audio);
thread.start();
System.out.println("iteration "+i);
}
}
}
Я использовал несколько коротких (менее 200 мс) волновых файлов с различными звуковыми нажатиями клавиш (всего 3) в каталоге ресурсов.
РЕДАКТИРОВАТЬ
Я прочитал ваши ответы и Комментарии. И я думаю, что, может быть, я их неправильно понял, потому что предложенные решения не работают, или, может быть, мне следовало четко заявить о том, чего именно я хотел. Кроме того, я должен отметить, что я не часто использую потоки (и понятия не имею, что такое мьютекс).
Поэтому я сначала объясню, что именно я хочу, чтобы программа делала. Он должен иметь возможность имитировать нажатие клавиш, и поэтому я использовал поток, потому что он позволяет перекрывать два звука нажатия клавиш, как при наборе текста настоящим человеком. По сути, используемые мной звуковые клипы - это звуки нажатия клавиш, а звук нажатия клавиш состоит из двух звуков: звука нажатия клавиши. звук нажатия клавиши.
Если в какой-то момент программа позволяет перекрывать два нажатия клавиш, это будет звучать так, как будто кто-то нажал одну клавишу, а затем другую, а затем отпустил первую клавишу. Вот как на самом деле печатается звук!
Теперь проблемы, с которыми я столкнулся при использовании предложенных решений: при непосредственном вызове метода run () AudioPlayer
public static void main(String[] args)
{
// Definitions here
while (running) {
Date previous = new Date();
Date delay = new Date(previous.getTime()+rnd.nextInt(300)+75);
// Setting the audio here
audio.run();
Date now = new Date();
if (now.before(delay)) {
try {
Thread.sleep(delay.getTime()-now.getTime());
} catch (InterruptedException e) {
}
}
System.out.println("iteration: "+(++i));
}
}
звуки воспроизводятся последовательно ( один за другим) и со скоростью, которая зависит от продолжительности ожидания AudioPlayer (или зависит от задержки, если задержка в методе main () больше, чем продолжительность ожидания AudioPlayer), что не годится, потому что это не будет звучать как обычная машинистка (больше похоже на того, кто новичок в наборе текста и все еще ищет все ключи при наборе).
При вызове метода join () потока AudioPlayer,
public static void main(String[] args)
{
//Variable definitions here
while (running) {
int delay = rnd.nextInt(200)+75;
try
{
Thread.sleep(delay);
}
catch (InterruptedException ie)
{
}
//Setting the AudioPlayer and creating its Thread here
thread.start();
try
{
thread.join();
}
catch(InterruptedException ie)
{
}
System.out.println("iteration "+(++i));
}
}
звуки воспроизводятся также последовательно и со скоростью, которая зависит от продолжительности ожидания AudioPlayer (или зависит от задержки, если задержка в методе main () превышает продолжительность ожидания AudioPlayer), которая, опять же, не годится по той же причине, что и раньше.
Итак, чтобы ответить на один вопрос комментатора. Да! есть и другие проблемы, о которых раньше не говорилось, и которые требуют, прежде всего, потоков.
Я нашел обходной путь, который «решает» мою проблему (но я не считаю это правильным решением, поскольку я в кстати, читерство): что я сделал, так это увеличил продолжительность ожидания AudioPlayer до того, что вряд ли будет достигнуто до остановки программы (24 часа) и из того, что я видел, он не использует много ресурсов даже после более чем час.
Вы можете проверить, что я хочу, что я получаю при запуске предлагаемых решений и что я получаю, используя мой обходной путь на этом видео на YouTube (К сожалению, StackOverflow не имеет функция загрузки видео. поэтому мне пришлось поставить его на YouTube).
РЕДАКТИРОВАТЬ Звуковые эффекты можно скачать здесь .