Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Wer kann mir helfen, einen Audio-Kanal zu buffern?

Empfohlene Antworten

Veröffentlicht

Hallo zusammen,

in meiner Routine verwende ich einen Audioplayer, welcher wie folgt aufgerufen wird:

player.writeStereo(byte A, byte B);

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

  • Autor
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.

  • Autor

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);

ä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....:D

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 ;)

  • Autor

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 von Devilmarkus

Ich glaub meine Boxen sind kaputt :D 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

  • Autor
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...

Archiv

Dieses Thema wurde archiviert und kann nicht mehr beantwortet werden.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.