2010-02-16 17 views
7

Çeşitli dijital sinyal işleme algoritmaları kullanarak Java'da işlemek istediğim bir kısa WAV dosyası koleksiyonum var. Bu amaç için 11025 Hz kare hızında kodlanmış bir dizi değerli örnek almam gerekiyor.Java ile bir örnek dizi içine bir WAV dosyası okunurken örnekleme hızı dönüştürme

Kaynak dosyalar 11025 Hz ve 44100 Hz dahil olmak üzere birkaç farklı örnek hızına sahiptir.

// read the WAV file 
FileInputStream fileInputStream = new FileInputStream(new File("test.wav")); 
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(fileInputStream); 

// copy the AudioInputStream to a byte array called buffer 
ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
byte[] data = new byte[4096]; 
int tempBytesRead = 0; 
int byteCounter = 0; 
while ((tempBytesRead = audioInputStream.read(data, 0, data.length)) != -1) { 
    bos.write(data, 0, tempBytesRead); 
      byteCounter += tempBytesRead; 
} 
bos.close(); 
byte[] buffer = bos.toByteArray(); 

AudioFileFormat audioFileFormat = new AudioFileFormat(AudioFileFormat.Type.WAVE, audioInputStream.getFormat(), (int)audioInputStream.getFrameLength()); 

// get the resulting sample array 
int[] samples = new int[audioFileFormat.getFrameLength()]; 
for (int i = 0; i < samples.length; i++) { 
    samples[i] = getSampleValue(i); // the getSampleValue method reads the sample values from the "buffer" array, handling different encoding types like PCM unsigned/signed, mono/stereo, 8 bit/16 bit 
} 

// RESULT: the "samples" array 

sorundur kodu düzgün farklı örnekleme hızları işlemek etmediğini,: İşte onları okumak için kullanmaya çalışıyorum kod. Böylece 44100 Hz kare hızı için 11025 Hz kare hızı için dört kat daha fazla örnek elde ediyorum. Kaynak dosyanın kare hızından bağımsız olarak ortaya çıkan örnek dizisinin 11025 Hz kare hızını kullanmasını istiyorum. Ben AudioInputStream okurken benim için kare hızını dönüştürmek için Java zorlamaya çalıştı, ama şunları birine bir istisna benzer olsun:

java.lang.IllegalArgumentException: Unsupported conversion: PCM_SIGNED 11025.0 Hz, 16 bit, mono, 2 bytes/frame, 44100.0 frames/second, little-endian from PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian 
    at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:955) 

Java Ses API öğretici okuyun: http://java.sun.com/docs/books/tutorial/sound/converters.html. Java Ses API'sinin işletim sistemimin bu tür bir dönüşümünü desteklemediği görülmektedir (Windows 7). Ve herhangi bir dış kütüphaneye bağımlılıktan kaçınmak istiyorum. Örnekleme oranı dönüşümünü kendi başıma yapmanın bir yolu var mı?

cevap

6

Örnek oranlar> 11025 Hz için, iki aşamalı bir işlem olan alt örnekleme yapmanız gerekir. İlk önce Nyquist kriterlerini karşılamak için alçak geçiren filtreye ihtiyacınız var ve sonra, örneğin 44.1 kHz'lik örnekleme hızı verileri için, 5.5 kHz'lik bir kesim frekansına sahip düşük geçiş filtresine ihtiyacınız olacaktır ve daha sonra 4'lük bir alt örnekleme oranı için her 4 numuneden 3'ünü atabilirsiniz. Desteklemek istediğiniz her alt örnekleme oranı için farklı bir filtreye ihtiyacınız olacak.

+0

Kesme frekansını nasıl hesap ederim? Ve bu adım neden gerekli? – pako

+2

Filtreleme nyquist etkisi nedeniyle neccissary 'dir. Kısacası: sr'niz 11025 hz ise ve girişinizde 5572,5 hz tonu varsa, bu 60 hz ton olarak yeniden üretilecektir. Nyquist wrap tamamen harmonik değildir (çeviri: gerçekten çirkin ve kötü sesler). Nyquist gürültüyü ortadan kaldırmak için yeni sr'inizin üzerindeki tüm girdileri filtrelemelisiniz. –

+2

ve "yeni sr'nizin yarısındaki tüm girdileri filtrele" ile demek istiyorum. Bu frekansın üzerinde sıfır içerik olduğundan emin olun - ve filtreleme miktarını ve kestiğiniz yeri kaynak materyalinize göre değişebilir - sonucu dinleyin, Filtreniz daha dik veya daha düşük bir kesme frekansına ihtiyaç duyuyorsa, eklenen gürültüden belli olacaktır. –

5

Kabul edilen yanıtın başka bir soruyu yanıtladığına inanıyorum - aynı problemi çözüyor (sesi küçültmek) ama başka bir şekilde (java ses API'sini kullanmanın yerine elle). Aynı şeyi aldım ve içine kazdım. (http://docs.oracle.com/javase/tutorial/sound/converters.html önerildiği üzere)

AudioFormat outDataFormat = new AudioFormat((float) 8000.0, (int) 8, (int) 1, true, false); 
AudioInputStream lowResAIS = AudioSystem.getAudioInputStream(outDataFormat, inFileAIS); 

Sorun standart java örnekleyerek gemi etmediğini bunun için (veya java ses API yön) gerçekten de doğru yoldur

(hatta stereo-mono dönüşüm) kodu (veya en azından kodun o kısmında bulunmaz - bkz. http://www.jsresources.org/faq_audio.html#convert_sample_rate).

jsresources sayfaları da yanıtları işaret eder: sadece 2 eklentiyi yüklemek hileyi yapar. En kolay bu hileyi (eğer wget olması koşuluyla) yapacak OSX Lion, Uzantıları dizinde bu eklentileri yüklemektir: Bu 2 kavanoz dosyaları ekledikten sonra

wget http://www.tritonus.org/tritonus_share-0.3.6.jar -O /Library/Java/Extensions/tritonus_share-0.3.6.jar 
wget http://www.tritonus.org/tritonus_remaining-0.3.6.jar -O /Library/Java/Extensions/tritonus_remaining-0.3.6.jar 

, her şey (sadece bir ekstra uyarı çalıştı: eğer Hem kanal sayısını hem de örnekleme oranını değiştirmek istiyorsanız, hala tek adım olarak desteklenmez).