2009-03-21 2 views
1

Ist es möglich, eine temporäre Datei zu erstellen, die eine "Schleife" einer WAV-Datei enthält?WAV-Datei in Java abspielen - wie verlängere oder verkette ich den Sound?

Oder ist es möglich, den Stream zu einem Stream Reader/Writer zu manipulieren?

Grundsätzlich möchte ich einige WAV-Datei für einen Zeitraum abspielen und wenn diese Zeit größer ist als die Länge der Zeit, die die WAV-Datei bietet, möchte ich Schleife.

Antwort

4
 AudioInputStream audioIn = AudioSystem.getAudioInputStream(url); 
    Clip clip = AudioSystem.getClip(); 
    clip.loop((int)(Math.ceil(timeRequested/audioIn.getFrameLength()))); 
+0

I habe ein paar Fragen - wie "anhefte" ich die Schleife an meine bestehende DataLine, die ich verwende? Was macht man mit dem Clip? - Wie sende ich das an eine SourceDataLine? – Tim

+0

Es wird automatisch an Ihre aktuelle aktive DataLine angehängt, Clip ist wie eine andere Player-Instanz, Sie können starten oder stoppen, wann immer Sie wollen.Sie können abfragen, um zu sehen, wie viele von ihnen gleichzeitig gespielt werden können, bei Bedarf können Sie Definieren Sie eine Warteschlange. Aber ich empfehle nicht, sich selbst zu mischen. –

+0

Ich werde es ausprobieren, aber nicht sicher, ob es mit der Dataline funktioniert, so wie mein Code existiert. Vielen Dank – Tim

0

Ich bin mir nicht sicher, ob ich die genauen Einschränkungen für die Implementierung einer Lösung verstehe, aber es scheint, als wäre die sauberste Methode, die Audiodaten beim ersten Durchspielen der Datei in einem Puffer zu speichern. Wenn es weitere Iterationen (ganz oder teilweise) gibt, die vom Benutzer gewünscht werden, überschreiben Sie einfach die Daten, die Sie zurückgespeichert haben, so oft wie gewünscht in die SourceDataLine.

Hier ist ein link zu einem Beispiel-Sound-Datei-Player (PCM), der Code hat, der sehr einfach zu ändern (oder nur von lernen) sein sollte. Ich habe auch ein paar (ungeprüften) Code gehackt, der nur die Logik zeigt, die ich oben beschrieben habe: (Sie wollen wahrscheinlich auch das, was ich unten habe, ändern, um den Regeln zu entsprechen, die nur Stücke von Daten mit einer Größe multiplizieren der Rahmengröße.)

public void playSoundFile(SourceDataLine line, InputStream inputStream, AudioFormat format, long length, float times) 
{ 
    int index = 0; 
    int size = length * format.getFrameSize(); 
    int currentSize = 0; 
    byte[] buffer = new byte[size]; 
    AudioInputStream audioInputStream = new AudioInputStream(inputStream, format, length); 
    while (index < size) 
    { 
     currentSize = audioInputStream.read(buffer, index, size - index); 
     line.write(buffer, index, currentSize); 
     index += currentSize; 
    } 

    float currentTimes = 1.0; 
    while (currentTimes < times) 
    { 
     float timesLeft = times - currentTimes; 
     int writeBlockSize = line.available(); 
     index = 0; 

     if (timesLeft >= 1.0) 
     { 
      while (index < size) 
      { 
       currentSize = ((size - index) < writeBlockSize) ? size - index : writeBlockSize; 
       line.write(buffer, index, currentSize); 
       index += currentSize; 
      } 
      currentTimes += 1.0; 
     } 
     else 
     { 
      int partialSize = (int)(timesLeft * ((float) size) + 0.5f); 
      while (index < partialSize) 
      { 
       currentSize = ((partialSize - index) < writeBlockSize) ? partialSize - index : writeBlockSize; 
       line.write(buffer, index, currentSize); 
       index += currentSize; 
      } 
      currentTimes += timesLeft; 
     } 
    } 
} 

Hoffnung, die hilft!

+0

, die eine Möglichkeit ist, aber es ist nicht ganz das, was ich suche - die Daten asynchron zu einem Spieler gesendet wird, und der aufrufenden Thread hat keine Ahnung, wie lange die Datei/Sound ist. – Tim

+0

Könnten Sie ein bisschen mehr Informationen über die Besonderheiten der Situation geben? Es gibt ein paar Dinge, die nicht spezifiziert sind (zB wer weiß die Länge der Datei/des Sounds und wie lange sie abgespielt werden sollte? Wenn es der Player ist, könnte der Player die oben beschriebene Caching-Methode durchführen.) –

0

Ich denke, ich werde die Frames pro Sekunde und Framesize Informationen im Audio-Eingangsstrom verwenden, um dies herauszufinden. Andere nützliche Informationen sind in der getMicrosecondPosition() -Methode des SourceDataLine-Objekts, um die Zeit/Dauer zu bestimmen, die bisher abgespielt wurde.

zusammen mit Mark-und Reset-Methoden in der Audio-Eingang Stream wahrscheinlich kümmern sich um alles.