# RingRecorder



## talbot (29. Jan 2010)

Hallöchen,
ich habe folgendes Problem. Ich habe mir den "SimpleAudioRecorder" von jsresources.com (Recording to an audio file (simple version)) in eine GUI eingebaut. Das funktioniert soweit auch ganz gut. Aber... jetzt möchte mich mir einen RingRekorder bauen. Das heisst ich möchte Aufgenommene Daten die länger als x Minuten sind verwerfen.

Ich habe mir nun einen Ringspeicher mit ByteArrays gebaut, der die eingelesenen Bytearrays immer wieder überschreibt.

Das funktioniert soweit. Allerdings weiss ich jetzt nicht, wie ich die SoundDatei erstellen soll.

Die Klasse AudioSystem bietet eine methode AudioSystem.write(m_audioInputStream, m_targetType, m_outputFile);
Diese liest aus einem inputstream in eine outputfile unter berücksichtigung des m_targetType's.

Ich habe meinen "Zwischenspeicher" jetzt wie gesagt als byteArray gespeichert. Wenn ich das einfach so in eine .WAV Datei schreibe, dann fehlen die Headerdaten und kein Player kann die wieder geben. Der AudioSystem.write Methode kann ich jedoch nur einen InputStream und kein ByteArray übergeben...

Hat jemand eine Idee wie man das lösen oder besser machen kann?


----------



## Hansdampf (29. Jan 2010)

```
AudioFormat af = new AudioFormat(44100 , 16, CHANNELS, true, false);
AudioInputStream a = new AudioInputStream(new ByteArrayInputStream(data), af, data.length);
AudioSystem.write(a, AudioFileFormat.Type.WAVE, file);
```
grob zusammenkopiert aus altem Code, damit kommst Du bestimmt klar.


----------



## talbot (30. Jan 2010)

Genau das habe ich ja bereits. Aber, da kann ich den Speicher der Datei nicht begrenzen. Bzw. so kann ich dem Programm nicht beibringen, dass es den Anfang der Datei ab einer bestimmten Größe verwerfen soll.

Ich möchte dauerhaft ein Gespräch aufzeichnen. Aber immer nur z.b. die letzten 5 Minuten. Alles was länger dauert wird verworfen. Wurde in den letzten 5 Minuten etwas gesagt, dass ich aber behalten will, möchte ich den aktuellen Speicherstand wegschreiben.

Ich habe mal ein Bild angehängt mit dem ich die Problematik verdeutlichen will. So wie du (Hansfampf) das beschrieben hast, klappt das was ich vorhabe nicht. Denn der Ringspeicher ist ja kein Stream und an die write Funktion kann ich nur einen Stream übergeben der dann in die File geschrieben wird.


----------



## Hansdampf (30. Jan 2010)

Dann kopier die byte[], bevor Du speichern willst, in ein neues byte[], so dass in byte[0] das erste erste byte der letzen 5 min steht...
ungefähr so:


```
public class RingTest {
		
	public static void main(String[] args){
		new RingTest();
	}
	
	public class Ring {
		private byte[] data;

		public Ring(int size) {
			data = new byte[size];
		}

		private int index;

		public void add(byte b) {
			data[index] = b;
			index++;
			index %= data.length;
		}

		
		public byte[] get() {
			int n = data.length;
			byte[] b = new byte[n];
			for (int i = 0; i < n; i++) {
				b[i] = data[(index +i) % n];
			}
			return b;
		}
	}

	public RingTest() {
		Ring r = new Ring(4);
		r.add((byte) 1);
		r.add((byte) 2);
		r.add((byte) 3);
		r.add((byte) 4);
		r.add((byte) 5);
		r.add((byte) 6);
		r.add((byte) 7);
		r.add((byte) 8);
		r.add((byte) 9);
		r.add((byte) 10);
		byte[] b = r.get();
		for (int i = 0; i < b.length; i++)
			System.out.println("pos:" + i + "=" + b[i]);
	}
}
}
```

output:

```
pos:0=7
pos:1=8
pos:2=9
pos:3=10
```

edit: habs verbessert. Eigentlich könnte man es auch geschickter machen (ohne ein neues byte[]), aber so gehts auch.
Ich hatte Deine Frage erst nicht richtig verstanden, weil Du ja schon einen RingBuffer hattest (?)


----------

