Devilmarkus Geschrieben 1. April 2010 Geschrieben 1. April 2010 Hallo zusammen, in meiner Routine verwende ich einen Audioplayer, welcher wie folgt aufgerufen wird: player.writeStereo(byte A, byte ; Nun habe ich folgendes Problem: Ich möchte ein "Pseudo Stereo" erreichen, mit einem gepufferten Kanal B. B ist identisch mit A, wenn ich Mono abspiele. Wie bastele ich mir nun einen Puffer dafür, so dass B mit 10ms Verzögerung abgespielt wird? MFG Markus Zitieren
perdian Geschrieben 1. April 2010 Geschrieben 1. April 2010 Und du glaubst dir kann geholfen werden, wenn du nichtmal verrätst aus was für einem Framework diese Player Klasse kommt? Deine erste Aufgabe sollte daher sein: Das hier lesen. Zitieren
Devilmarkus Geschrieben 1. April 2010 Autor Geschrieben 1. April 2010 Und du glaubst dir kann geholfen werden, wenn du nichtmal verrätst aus was für einem Framework diese Player Klasse kommt? Deine erste Aufgabe sollte daher sein: Das hier lesen. Nunja, im Prinzip ist es doch egal, aus welchem Framework dies kommt. Es könnte auch ein ganz normaler Buffer sein, nicht für Audio sondern eine andere Verzögerung. Hier nun die gesamte Klasse zu posten, wäre wirklich zu komplex. Ich werd mal versuchen, ein byte[] Array zu erschaffen, welches an letzter Stelle mit dem aktuellen Byte B gefüllt wird, wovon das erste Byte gespielt wird, und welches sich mit System.ArrayCopy(....) selbst verschiebt. Zitieren
Devilmarkus Geschrieben 1. April 2010 Autor Geschrieben 1. April 2010 Hab es herausgefunden: /* the buffer */ int[] circlebuffer = new int[2000]; /* write position */ int writepos = (2000 - 1); /* read position */ int readpos = 0; /* write value into buffer and update write position */ void buffer_write(int val) { circlebuffer[writepos] = val; writepos = (writepos + 1) % circlebuffer.length; } /* read value from buffer and update read position */ int buffer_read() { int val = circlebuffer[readpos]; readpos = (readpos + 1) % circlebuffer.length; return val; } In meiner Routine rufe ich nun Dieses hier auf: if (Switches.dbeffect){ buffer_write(rightChannel); rightChannel = buffer_read(); } player.writeStereo(leftChannel, rightChannel); Zitieren
Devilmarkus Geschrieben 1. April 2010 Autor Geschrieben 1. April 2010 Hier ein Beispiel des Buffers: http://cpc-live.com/silkworm.zip Das CPC-MDL wird Mono abgespielt. Mit dem Buffer klingt es besser Zitieren
wakoz Geschrieben 7. April 2010 Geschrieben 7. April 2010 äm ich hoffe dir ist bewusst das nur Mono aus zwei boxen ist und das richtiger Stereo Sound daraus besteht das es zwei unterschiedliche Audiospuren gibt:cool: so genug klug ges.... das Thema ist mal interessant :cool: Ich versuche aus einzelnen Double werten eine Ton reihe zu generieren, leider habe ich immer ein knacken zwischen zwei tönen :eek jemand Ahnung woran das liegt? oder wie ich das weg bekomme? package sound.model; import java.util.ArrayList; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; public class SoundGenerator { public SoundGenerator(){ System.out.println("Erzeugt"); } /** * Generates a tone. * * @param herz * Base frequency (neglecting harmonic) of the tone in cycles per * second * @param milliseconds * The number of milliseconds to play the tone. * @param volume * Volume, form 0 (mute) to 100 (max). * @param addHarmonic * Whether to add an harmonic, one octave up. */ public void generateTone(Double herz, int milliseconds, int volume, boolean addHarmonic) throws LineUnavailableException { float frequency = 44100; byte[] buf; AudioFormat af; if (addHarmonic) { buf = new byte[2]; af = new AudioFormat(frequency, 8, 2, true, false); } else { buf = new byte[1]; af = new AudioFormat(frequency, 8, 1, true, false); } SourceDataLine sdl = AudioSystem.getSourceDataLine(af); sdl.open(af); sdl.start(); for (int i = 0; i < milliseconds * frequency / 1000; i++) { double angle = i / (frequency / herz) * 2.0 * Math.PI; buf[0] = (byte) (Math.sin(angle) * volume); if (addHarmonic) { double angle2 = (i) / (frequency / herz) * 2.0 * Math.PI; buf[1] = (byte) (Math.sin(2 * angle2) * volume * 0.6); sdl.write(buf, 0, 2); } else { sdl.write(buf, 0, 1); } } sdl.drain(); sdl.stop(); sdl.close(); } /** * Generates a tone. * * @param herz * Base frequency (neglecting harmonic) of the tone in cycles per * second * @param milliseconds * The number of milliseconds to play the tone. * @param volume * Volume, form 0 (mute) to 100 (max). * @param addHarmonic * Whether to add an harmonic, one octave up. */ public void generateTone(ArrayList<Double> soundValues, int milliseconds, int volume, boolean addHarmonic) throws LineUnavailableException { for (Double herz : soundValues) { float frequency = 44100; byte[] buf; AudioFormat af; if (addHarmonic) { buf = new byte[2]; af = new AudioFormat(frequency, 8, 2, true, false); } else { buf = new byte[1]; af = new AudioFormat(frequency, 8, 1, true, false); } SourceDataLine sdl = AudioSystem.getSourceDataLine(af); sdl.open(af); sdl.start(); for (int i = 0; i < milliseconds * frequency / 1000; i++) { double angle = i / (frequency / herz) * 2.0 * Math.PI; buf[0] = (byte) (Math.sin(angle) * volume); if (addHarmonic) { double angle2 = (i) / (frequency / herz) * 2.0 * Math.PI; buf[1] = (byte) (Math.sin(2 * angle2) * volume * 0.6); sdl.write(buf, 0, 2); } else { sdl.write(buf, 0, 1); } } sdl.drain(); sdl.stop(); sdl.close(); } } private int milliseconds; private int volume; private boolean addHarmonic; private float frequency = 44100; private byte[] buf; private SourceDataLine sdl; public void setValues( int milliseconds, int volume, boolean addHarmonic){ this.milliseconds = milliseconds; this.volume = volume; this.addHarmonic = addHarmonic; } public void setMilliseconds(int milliseconds){ this.milliseconds = milliseconds; } public void setVolume(int volume){ this.volume = volume; } public void startSound() throws LineUnavailableException{ AudioFormat af; if (addHarmonic) { buf = new byte[2]; af = new AudioFormat(frequency, 8, 2, true, false); } else { buf = new byte[1]; af = new AudioFormat(frequency, 8, 1, true, false); } sdl = AudioSystem.getSourceDataLine(af); sdl.open(af); sdl.start(); } public void writeHerz(Double herz){ for (int i = 0; i < milliseconds * frequency / 1000; i++) { double angle = i / (frequency / herz) * 2.0 * Math.PI; buf[0] = (byte) (Math.sin(angle) * volume); if (addHarmonic) { double angle2 = (i) / (frequency / herz) * 2.0 * Math.PI; buf[1] = (byte) (Math.sin(2 * angle2) * volume * 0.6); sdl.write(buf, 0, 2); } else { sdl.write(buf, 0, 1); } } } public void stopSound(){ sdl.drain(); sdl.stop(); sdl.close(); } } Die Tonreihe ist kein Problem aber das Knacken das ich nun so viele Methoden habe liegt daran das ich bereits einiges versucht habe die reihe ohne knacken zu erzeugen, ursprünglich gab es nur die Methode generateTone(Double herz, int milliseconds, int volume, boolean addHarmonic) Ich hoffe das der Thread starter helfen kann Zitieren
Devilmarkus Geschrieben 7. April 2010 Autor Geschrieben 7. April 2010 (bearbeitet) Ich weiss, dass ich Mono auf 2 Lautsprechern wiedergebe. Aber durch die Verzögerung im rechten Kanal erreiche ich eine Art Raumklang ----- Auf Anhieb fällt mir nur grad auf, dass Du einen sehr kleinen Buffer verwendest. Ausserdem: Ändere mal: af = new AudioFormat(frequency, 8, 2, true, false); zu: af = new AudioFormat(frequency, 8, 2, false, false); Das sollte das Knacken beheben! (In allen Fällen ändern) Bearbeitet 7. April 2010 von Devilmarkus Zitieren
Devilmarkus Geschrieben 7. April 2010 Autor Geschrieben 7. April 2010 Übrigens: Einen "Live" Test meines Effektes kann man hier hören: CPCWiki People Network - Devilmarkus's webcpc - Go West (Digiblaster) (Einfach auf das Schwarze PNG "Start Here" klicken und einen Moment warten...) Zitieren
wakoz Geschrieben 7. April 2010 Geschrieben 7. April 2010 Ich glaub meine Boxen sind kaputt oder gehört das knacken da rein? GoWest ist aber immer noch ein guter titel mit buffer meinst du das byte Array wie würde man dies sinnvoll vergrößern? Muss ja schließlich mit Daten gefüllt werden Danke Zitieren
Devilmarkus Geschrieben 7. April 2010 Autor Geschrieben 7. April 2010 mit buffer meinst du das byte Array wie würde man dies sinnvoll vergrößern? Muss ja schließlich mit Daten gefüllt werden Du füllst es doch schon mit Daten. Fülle einfach weiter und spiele dann ab, wenn der Buffer voll ist. Mal aus meinem Source zitiert: public void writeStereo(int a, int { a = a ^ 0x80; b = b ^ 0x80; switch (format) { case SoundUtil.ULAW: data[offset] = SoundUtil.ulawToUPCM8((byte) a); data[offset + 1] = SoundUtil.ulawToUPCM8((byte) ; break; case SoundUtil.PCM8: data[offset] = SoundUtil.ulawToPCM8((byte) a); data[offset + 1] = SoundUtil.ulawToPCM8((byte) ; break; case SoundUtil.UPCM8: data[offset] = (byte) a; data[offset + 1] = (byte) b; break; } if ((offset += 2) == data.length) { line.write(data, 0, data.length); offset = 0; } updates++; } }[/code] Hier ist "data" mein Buffer... Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.