Głośność odtwarzanego pliku w czasie rzeczywistym

0

Witam, bardzo serdecznie, w Javie piszę od niedawna i natknąłem się na pewien problem, który przyprawia mnie o ból głowy. Dwudniowe buszowanie po googlach, jak i stackoverflow, nie przyniosło oczekiwanego rezultatu. Mianowicie, chcę stworzyć UV Meter, a dokładniej coś przypominającego pasek rozszerzający się, zależnie od głośności dźwięku w danej chwili, tak jak np. pasek jak klikniemy na głośniczek w systemie Windows lub podobne elementy w różnych odtwarzaczach muzyki czy programach takich jak AudaCity, FL Studio itd. I tu pojawia się mój problem nie ma mogę znaleźć metody, która zwracała by aktualny poziom głośności dźwięku ( w czasie rzeczywistym ). A informację, które znalazłem podpowiadające, żeby analizować linie utworu bajt po bajcie są dla mnie mówiąc wprost nie jasne. Starałem się też poszukać jakieś biblioteki, klasy z gotową funkcją mającą chociaż zbliżone właściwości do owych, które potrzebuję, ale na tym polu też poległem.
Bardzo proszę o pomoc lub podpowiedź, gdzie szukać, dalej. Do odtwarzania utworu .wav użyłem klasy Clip z bibliotek javax.sound.sampled.*

Z góry dziękuje za wszelką pomoc.

0

W java co prawda nie piszę ale w google pod hasłem "volumemeter java.sound" wpadłem na to. Może okaże się pomocne.

0

Dzięki za chęci, ale to wciąż nie to czego szukam. To mi wygląda na jedną z klas biblioteki javax.sound.sampled.

1
Xardas348 napisał(a):

nie ma mogę znaleźć metody, która zwracała by** aktualny poziom głośności dźwięku ( w czasie rzeczywistym ).**

opis metody getLevel() z linka, który wrzuciłem:

Obtains the current volume level for the line...

Xardas348 napisał(a):

Dzięki za chęci, ale to wciąż nie to czego szukam
w takim razie czego szukasz?

0

Mianowicie, mam poniższy kod i tak jak widać odtwarzam w nim plik muzyczny *.wav. I tak dokładnie chcę pobrać jego aktualną głośność by wykorzystać ją do animacji ( zależnie od zwróconej wartości będę chciał wyświetlać odpowiednio szeroki prostokąt itd). Tymczasowo wyświetlam sobie wartość volume w linijce **tekst.setLabel( ); ** w pętli while(); . Jednak funckja volume.getLevel() nie przynosi oczekiwanych rezultatów, zarówno dla Clip, jak i SoruceDataLine zwraca stale nie **zmienne ** Volume: -1.0, nie zależnie od tego jak bardzo się gimnastykuje z tym kodem.

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.File;

import javax.sound.sampled.*;

import acm.graphics.GLabel;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;

public class Graphics extends GraphicsProgram {

	private static final long serialVersionUID = 1L;
	
	//Audio
	//private static final int	BUFFER_SIZE = 128000;
	private String				FILENAME = "D:\\Xardas\\Eclipse_workspace\\BlankFramework\\nie_jestem.wav";
	private File				audioFile;
	//private byte[]				audioBytes;
	private AudioFormat			audioFormat;
	private AudioInputStream	audioStream;
	//private SourceDataLine		audioLine;
    private Clip				audioClip;
    private javax.sound.sampled.Mixer.Info[] mixers;
    
    //Tekst
    private String tresc = "Puste";
	
	public void run(){
		
		GLabel tekst = new GLabel( tresc );
		tekst.setFont("Times New Roman-20");
		tekst.setColor( Color.RED );
		tekst.setLocation( 100, 100 );
		
		add( tekst );
		
		//Utwór
		
		try {

			mixers = AudioSystem.getMixerInfo();
			
			audioFile = new File(FILENAME);
			audioStream = AudioSystem.getAudioInputStream(audioFile);

			audioBytes = getWAVByte( audioFile );

			audioClip = (Clip) AudioSystem.getLine( new Line.Info(Clip.class));
			audioClip.open( audioStream );
			
			DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
			audioLine = (SourceDataLine) AudioSystem.getLine(info);

			audioFormat = audioStream.getFormat();
			
			audioClip.loop(0);

		}
        catch (Exception e) {
            e.printStackTrace();
            System.exit(1); }
        
       while ( true ) {
    	   
    	  FloatControl volume = (FloatControl) audioClip.getControl( FloatControl.Type.MASTER_GAIN ); 
    	   
        	tekst.setLabel(
        			" Volume: " + audioClip.getLevel() +
        			" FramePosition: " + audioClip.getFramePosition() );
        	tekst2.setLabel( "" + audioClip.getMicrosecondPosition() );
        	
        	if ( !audioClip.isRunning() ) { break; }
        	pause( 1000/60 ); }
        
	}

}
1

Pobieraj pozycję odtwarzania i na jej podstawie analizuj strumień pliku audio - klasa FormatConversionProvider może być pomocna.

0

Znalazłem taką stronę w sieci, gdzie rozważany był podobny problem, tylko ze zmianą głośności poprzez analizę strumienia http://stackoverflow.com/questions/14485873/audio-change-volume-of-samples-in-byte-array.

Pojawiają się tam dwie funkcje, pierwsza zwraca tablicę, zawierającą bajt po bajcie plik dźwiękowy wav.

private byte[] getAudioFileData(final String filePath) {
    byte[] data = null;
    try {
    final ByteArrayOutputStream baout = new ByteArrayOutputStream();
    final File file = new File(filePath);
    final AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);

    byte[] buffer = new byte[4096];
    int c;
    while ((c = audioInputStream.read(buffer, 0, buffer.length)) != -1) {
        baout.write(buffer, 0, c);
    }
    audioInputStream.close();
    baout.close();
    data = baout.toByteArray();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return data;
}

Druga natomiast, rzekomo zwiększa głośność pojedynczych bajtów, na podstawie uzyskanej z powyższej funkcji tablicy złożonej z bajtów wav'a.

private byte[] adjustVolume(byte[] audioSamples, double volume) {
    byte[] array = new byte[audioSamples.length];
    for (int i = 0; i < array.length; i+=2) {
        // convert byte pair to int
        int audioSample = (int) ((audioSamples[i+1] & 0xff) << 8) | (audioSamples[i] & 0xff);

        audioSample = (int) (audioSample * volume);

        // convert back
        array[i] = (byte) audioSample;
        array[i+1] = (byte) (audioSample >> 8);

    }
    return array;
}

Poeksperymentowałem z nimi i amplituda wydaje się pokrywać z tym co system wyświetla na głośniczku. Tak, więc dziękuje za pomocą wszystkim. Tym większe dzięki 0x666 za podpowiedź. Na bazie tego myślę, że uda mi się wykonać mój mały projekt na zajęcia.
Wrzucam te informację tutaj, a nóż się komuś przydadzą albo ktoś wykryje w nich błąd i je poprawi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1