Я попытался изменить частоту дискретизации файла WAV с помощью javax.sound library.Невозможно прочитать один байт из AudioInputStream
После реализации моих желает методов я пробовал его, и это сработало! Но созданный файл .wav
занимает всего пару байт. Если быть точным, то только 2.090 байт от первоначально ~ 50 МБ
Проблема в том, что Java не может прочитать один байт из моего открытого AudioInputStream.
FYI, используемый файл является продуктом преобразования mp3-файла в JLayer. Он отлично работает, с JLayer нет проблем, но я полагаю, что лучше, если я опубликую весь свой исходный код. Примечание. Я использовал множество System.out.printlns для ведения журнала.
Итак, сначала я импортирую все необходимые библиотеки, так как вы можете видеть, что я также импортировал JLayer.
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import javax.sound.sampled.*;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JOptionPane;
import javazoom.jl.converter.Converter;
import javazoom.jl.decoder.JavaLayerException;
public class MyConverter {
private static AudioInputStream lowResAis = null;
private static AudioInputStream audioInputStream = null;
После установки этих глобальных констант я писал мой основной и предварительно выбранный демонстрационный файл для целей тестирования.
public static void main(String[] args) {
MyConverter converterdemo = new MyConverter();
String wavfilepath = "C:\\Users\\JohnDoe\\Desktop\\Second Nature.wav";
File f = new File(wavfilepath);
converterdemo.convertMp3toWav("C:\\Users\\JohnDoe\\Desktop\\Second Nature.mp3", "C:\\Users\\JohnDoe\\Desktop\\Second Nature.wav");
converterdemo.compressWavFile(wavfilepath);
converterdemo.writeToSoundFile(f);
System.out.println("Everything worked!");
}
Это мой преобразования метод
public void convertMp3toWav(String sourcefilename, String targetfilename){
Converter con = new Converter();
try {
con.convert(sourcefilename, targetfilename);
System.out.println("Wav File converted!");
} catch (JavaLayerException e) {
this.showOptionPane("Could not convert by using JLayer!");
}
}
Метод преобразования прекрасно (поверьте мне, нет никаких проблем с аудиофайле), но вот метод, о котором я я волнуясь немного
После добавления этой строки: System.out.println(AudioSystem.getAudioFileFormat(audioInputStream).getByteLength());
Я получаю следующее сообщение об ошибке: java.io.IOException: cannot read a single byte if frame size > 1
Я не могу прочитать из собственного потока.
public void compressWavFile(String sourcefilename){
try {
InputStream musicfile = new BufferedInputStream(new FileInputStream(sourcefilename));
audioInputStream = AudioSystem.getAudioInputStream(musicfile);
AudioFormat format = audioInputStream.getFormat();
AudioFormat outDataFormat = new AudioFormat((float) 22000.0,
(int) 16, (int) 1, true, false);
if(AudioSystem.isConversionSupported(outDataFormat, format)){
System.out.println("Conversion Supported!");
lowResAis = AudioSystem.getAudioInputStream(outDataFormat, audioInputStream);
}
System.out.println("low res created!");
} catch (UnsupportedAudioFileException e) {
this.showOptionPane("Audio File not Supported!"); e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
я намеренно не использовал попробовать с ресурсом, из-за какой-то колдовства вновь созданный AudioInputStream
также закрыт после закрытия оригинального audioInputStream
, который в настоящее время является статической переменной.
public void writeToSoundFile(File out){
if(AudioSystem.isFileTypeSupported(AudioFileFormat.Type.WAVE, lowResAis)){
try {
AudioSystem.write(lowResAis, AudioFileFormat.Type.WAVE, out);
System.out.println("New wav file written!");
} catch (IOException e) {
e.printStackTrace();
this.showOptionPane("Could not write to new Audio File!");
}
}
try {
System.out.println("closing stream!");
lowResAis.close();
audioInputStream.close();
} catch (IOException e) {
this.showOptionPane("Could not close Audio Stream!");
e.printStackTrace();
}
}
Это последний бит только там писать вновь созданный AudioInputStream
к данному File
. Я также не думаю, что здесь все может пойти не так.
Я действительно думаю, что есть проблема с моими AudioInputStreams, потому что это единственный момент, когда что-то может пойти не так.
EDIT:
Я добавил новый метод "showOptionPane", чтобы остаться thread safe
все время.
private void showOptionPane(String msg){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
JOptionPane.showMessageDialog(null, msg, "Error",
JOptionPane.ERROR_MESSAGE);
}
});
}
Не помещайте JOptionPane.showMessageDialog (...) в водосборный блоке, если вы уверены, что весь файл writeToSoundFile (...) запускается в потоке Swing Swing! –
Почему я не должен? Это то же самое, как если бы я запускал System.out.println(); Также, как я упомянул, он предназначен только для ведения журнала и будет удален, когда будет завершен – Einstein
Это не то же самое, что System.out.println (...), потому что он вызывает окно, используя библиотеку Swing. Библиотека Swing не является потокобезопасной, поэтому рисование с ней, если не в потоке пользовательского интерфейса, может привести к повреждению состояния пользовательского интерфейса. Именно по этой причине все обучающие программы Swing начинаются с встраивания вызовов рисования в SwingUtilities.invokeLater (....). Вы можете вызывать позже свою JOptionPane, если хотите, но вызов ее из потока, отличного от UI, является неправильным в каждой ситуации. Подробнее см. Http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html. –