Zurück   Flashforum > Flash > ActionScript > ActionScript 3

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 28-09-2007, 08:08   #1 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.271
[PopForge Audio] Eine Sekunde Audio generieren

Nach der Konferenz bekomme ich diverse Anfragen, ob ich das Beispielscript, mit dem ich das Audio generiert habe veröffentlichen kann.

Benötigt wird nur die PopForge Library. Ich beantworte gerne weitere Fragen hier.

Code:
package
{
	import de.popforge.audio.output.Audio;
	import de.popforge.audio.output.Sample;
	import de.popforge.audio.output.SoundFactory;
	
	import flash.display.Sprite;
	import flash.media.Sound;

	public class Main extends Sprite
	{
		public function Main()
		{
			init();
		}
		
		private function init(): void
		{
			var samples: Array = new Array();
			
			var phase: Number = 0.0;
			
			var frequence: Number = 440.0;
			
			var sampleRate: Number = 44100.0;
			
			var amplitude: Number;
			
			var sample: Sample;
			
			for( var i: int = 0 ; i < 44100 ; i++ )	//-- One second of audio
			{
				sample = samples[i] = new Sample();
				
				amplitude = Math.sin( phase * Math.PI * 2.0 );

				phase += frequence / sampleRate;
				
				sample.left = sample.right = amplitude;
			}
			
			SoundFactory.fromArray( samples, Audio.STEREO, Audio.BIT16, Audio.RATE44100, onSoundCreated );
		}
		
		private function onSoundCreated( sound: Sound ): void
		{
			sound.play();
		}
	}
}
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 29-09-2007, 01:10   #2 (permalink)
agedoubleju
Gast
 
Beiträge: n/a
Ich war leider nicht auf der Konferenz, kannst du bitte noch ein paar Worte zur Thematik verlieren? Habe ich das richtig verstanden, dass dein Script eine Sekunde aus einem Audio rauslöst und abspielt?
  Mit Zitat antworten
Alt 29-09-2007, 16:14   #3 (permalink)
faulancer
 
Benutzerbild von zerlettino
 
Registriert seit: Feb 2003
Beiträge: 281
Hi,
toll, dass das framework jetzt opensource ist.
Ich hab mal einen kleinen Test gemacht bei dem 2 wav files geladen werden. Dann werden die Samples von beiden Quellen ineinander kopiert.
Hat mich überrascht, dass es auf anhieb funktioniert hat

Jetzt quälen mich 2 Fragen:

1) wie kann ich als Quelle mp3s benutzen?
2) wie kann ich einen Endlos-Audiostream erzeugen und in diesen ständig neue Samples hinein-mergen? Mit der AudioBuffer Klasse hatte ich keinen Erfolg.
Mein Ziel ist so ne Art Stepsequenzer.


Code:
package
{
	import de.popforge.audio.output.Audio;
	import de.popforge.audio.output.Sample;
	import de.popforge.audio.output.SoundFactory;
	import de.popforge.format.wav.WavFormat;
	
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.media.Sound;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	
	public class SampleMerge
	{		
  		private var wavSamples:Array;
  		private var finalSamples:Array;
  		  		
		public function SampleMerge()
		{         	         	
			init();
		} 
		
		private function init():void
		{	
			wavSamples = [];
					
			var loader:URLLoader = new URLLoader();
	        loader.dataFormat = URLLoaderDataFormat.BINARY;
	        loader.addEventListener(Event.COMPLETE, onLoad);
	        var request:URLRequest = new URLRequest("samples/drums_180224.wav");
	        loader.load(request);
			
			var loader2:URLLoader = new URLLoader();
	        loader2.dataFormat = URLLoaderDataFormat.BINARY;
	        loader2.addEventListener(Event.COMPLETE, onLoad);
	        var request:URLRequest = new URLRequest("samples/scratch_720896.wav");
	        loader2.load(request);
		}
		
		private function onLoad(e:Event):void
		{
			var loader:URLLoader = URLLoader(e.target);
			var b:ByteArray = loader.data;
			var waveFormat:WavFormat = WavFormat.decode( b );
			wavSamples.push( waveFormat.samples );
			if (wavSamples.length == 2) mergeSamples();
		}
		
		private function mergeSamples():void
		{
			finalSamples = [];
			
			for( var i: int = 0 ; i < wavSamples[0].length ; i++ )
			{
				finalSamples[i] = merge( wavSamples[0][i] , wavSamples[1][i] );
			}
			
			var timer:Timer = new Timer(500,1);
      		timer.addEventListener(TimerEvent.TIMER,generate);
      		timer.start();	
		}
		
		private function merge(s1:Sample , s2:Sample ):Sample
		{
			return new Sample( (s1.left+s2.left) / 2 , (s1.right+s2.right) / 2 );
		}
		
		private function generate(e:Event):void
		{			
			SoundFactory.fromArray( finalSamples , Audio.STEREO, Audio.BIT16, Audio.RATE44100, onSoundCreated );
		}
		
		private function onSoundCreated( sound: Sound ): void
		{
			sound.play(0,5);
		}
			
				
	}
}
zerlettino ist offline   Mit Zitat antworten
Alt 29-09-2007, 17:00   #4 (permalink)
\x3a\x6f\x29
 
Benutzerbild von [je]
 
Registriert seit: Apr 2004
Ort: paris
Beiträge: 806
Wärst du mal im Workshop gewesen Der Audiobuffer ist die richtige Wahl. Was hat denn nicht funktioniert?

Vielleicht helfen dir die Synthesizer Sources aus dem Rent an idea Thread ja schon weiter.

MP3: Geht nicht ohne die MP3 vorher zu decoden. Ich glaube das ist eine ganz schöne Arbeit.

@agedoubleju: Hier wird genau eine Sekunde Audio synthetisiert. Wobei die Synthese sich auf eine einfache Sinuswelle beschränkt.
__________________
joa ebert
http://blog.joa-ebert.com/ - http://www.joa-ebert.com/
[je] ist offline   Mit Zitat antworten
Alt 29-09-2007, 17:30   #5 (permalink)
habs vergessen
 
Benutzerbild von pwdVergesser
 
Registriert seit: Feb 2006
Beiträge: 990
Wirklich superinteressantes zeug´s!

jetzt nur noch ein wenig mehr zeit um sich ohne stress mal damit zu beschäftigen...


pwd
__________________
Blog/Lab Xing

Geändert von pwdVergesser (29-09-2007 um 18:15 Uhr)
pwdVergesser ist offline   Mit Zitat antworten
Alt 29-09-2007, 18:06   #6 (permalink)
Der Wunderhund
 
Benutzerbild von gaspode
 
Registriert seit: Jun 2002
Ort: Hattingen
Beiträge: 10.515
Zitat:
Zitat von pwdVergesser Beitrag anzeigen
jetzt nur noch ein wenig mehr zeit um sich ohne stress mal damit zu beschägtigen...
Ist doch was für Deinen Urlaub!

@André Michelle: Wie immer ein super Vortrag!
Aber ich glaube die Vermieter der Räumlichkeiten
haben ganz schön um ihre Boxen gebangt, als Du
da die Sinuswellen durchgejagt hast.

gruß, gaspode
gaspode ist offline   Mit Zitat antworten
Alt 29-09-2007, 18:09   #7 (permalink)
habs vergessen
 
Benutzerbild von pwdVergesser
 
Registriert seit: Feb 2006
Beiträge: 990
Zitat:
Zitat von gaspode Beitrag anzeigen
Ist doch was für Deinen Urlaub!
genau.
da freut sich die familie bestimmt... =)
__________________
Blog/Lab Xing
pwdVergesser ist offline   Mit Zitat antworten
Alt 30-09-2007, 01:07   #8 (permalink)
faulancer
 
Benutzerbild von zerlettino
 
Registriert seit: Feb 2003
Beiträge: 281
danke für den Tipp mit dem Synthesizer - jetzt hats geklappt mit dem AudioBuffer.
Das Problem war wohl, dass die Samples immer geklont werden müssen bevor sie an den Audio-Buffer gehen-
ohne klonen werden alle nur genau 1x abgespielt,
dann herrscht Stille.

Hier der Code von meinem erfolgreichen Test:

Code:
package
{
	import de.popforge.audio.output.Sample;
	import de.popforge.audio.processor.IAudioProcessor;
	import de.popforge.format.wav.WavFormat;
	
	import flash.utils.ByteArray;

	public class Synth implements IAudioProcessor
	{
		
		[Embed(source="samples/drums_180224.wav", mimeType="application/octet-stream")]
		static private const Drums: Class;		
		
		[Embed(source="samples/piano_720896.wav", mimeType="application/octet-stream")]
		static private const Piano: Class;	
		
		private var track1Samples:Array;
		private var track2Samples:Array;

		private var track1Position: int;
		private var track2Position: int;
		
		private var sampleCounter : int;
		
		public function Synth()
		{
			init();
		}
		
		private function init(): void
		{
			sampleCounter = 0;
			track1Position = 0;
			track1Samples = getSamples( new Drums() );
			track2Position = 0;
			track2Samples = getSamples( new Piano() );
		}
		
		public function getSamples( wav:ByteArray ):Array
		{
			return WavFormat.decode( wav ).samples;
		}
		
		public function processAudio( samples: Array ): void
		{		
			var s:Sample;
			var mergeSamples:Array = [];
			
			for( var i: int = 0 ; i < samples.length ; ++i )
			{
				mergeSamples = [];
				
				s = Sample( track1Samples[track1Position] ).clone();
				mergeSamples.push(s);
				
				s = Sample( track2Samples[track2Position] ).clone();
				mergeSamples.push(s);
				
				samples[i] = mergeAll( mergeSamples );
				
				track1Position++;
				if (track1Position > track1Samples.length-1) track1Position = 0;
				
				track2Position++;
				if (track2Position > track2Samples.length-1) track2Position = 0;
				
				sampleCounter++;				
			}
		}
		
		public function mergeAll( sa:Array ):Sample
		{
			var r:Number = 0;
			var l:Number = 0;
			
			for( var i: int = 0 ; i < sa.length ; ++i )
			{
				r += Sample( sa[i] ).right;
				l += Sample( sa[i] ).left;
			}
						
			return new Sample(l,r);
		}
		
		public function reset():void
		{
		}
		
	}
}
solange man nur wav Files nehmen kann, ist die Sache halt nicht
ganz ISDN-freundlich
zerlettino ist offline   Mit Zitat antworten
Alt 30-09-2007, 06:58   #9 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.271
Zitat:
Das Problem war wohl, dass die Samples immer geklont werden müssen bevor sie an den Audio-Buffer gehen-
ohne klonen werden alle nur genau 1x abgespielt,
dann herrscht Stille.
Das ist nicht der Fall. Aber generell wundere ich mich über deinen Aufwand. Was du da machst ist extrem teuer. Man sollte immer vermeiden neue Samples zur Laufzeit zu generieren. Du erzeugst 4 x 44100 neue Sample Instanzen und 44100 Array Instanzen pro Sekunde Audio.
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 30-09-2007, 09:22   #10 (permalink)
faulancer
 
Benutzerbild von zerlettino
 
Registriert seit: Feb 2003
Beiträge: 281
mhh, stimmt bei mehreren "tracks" kann ich mir das clone() sparen,
weil ich ja sowieso aus den benutzten Samples ein Neues generieren muss.

Aber wie kann ich diesen Step optimieren? Ich muss ja die versch. Tracks zusammenbringen.

Ich könnte mir halt vorstellen, dass ich z.b. den Buffer relativ lang mache.

30 Sekunden wären kein Problem.

Bin da für Tipps dankbar
zerlettino ist offline   Mit Zitat antworten
Alt 30-09-2007, 09:28   #11 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.271
Zitat:
mhh, stimmt bei mehreren "tracks" kann ich mir das clone() sparen,
weil ich ja sowieso aus den benutzten Samples ein Neues generieren muss.
Nein - erzeuge niemals neue Sample Instanzen zur Laufzeit!

Benutzt du denn die Samples des AudioBuffers?
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 30-09-2007, 21:27   #12 (permalink)
faulancer
 
Benutzerbild von zerlettino
 
Registriert seit: Feb 2003
Beiträge: 281
Ja, die Samples vom Buffer werden benutzt.
Das ganze basiert ja auf eurem Synthesizer Code:
Workshop: Rent an idea (Joa Ebert, Mario Klingemann und André Michelle)

Ich hab das jetzt mal so optimiert, dass keine neuen Samples mehr erzeugt werden. Läuft rund soweit

Auf jedenfall gefällt mir das so besser, als mit mehreren Soundobjekten gleichzeitig zu hantieren- zumal das Timing hier einfach viel sicherer ist.

Audiobuffer ist ne feine Sache

Code:
package
{
	import de.popforge.audio.output.Sample;
	import de.popforge.audio.processor.IAudioProcessor;
	import de.popforge.format.wav.WavFormat;
	
	import flash.utils.ByteArray;

	public class Synth implements IAudioProcessor
	{
		
		[Embed(source="samples/drums_180224.wav", mimeType="application/octet-stream")]
		static private const Drums: Class;		
		[Embed(source="samples/piano_720896.wav", mimeType="application/octet-stream")]
		static private const Piano: Class;	
		
		private var track1Samples:Array;
		private var track2Samples:Array;
		private var track1Position: int;
		private var track2Position: int;
		
		public function Synth()
		{
			init();
		}
		
		private function init(): void
		{
			track1Position = 0;
			track1Samples = getSamples( new Drums() );
			track2Position = 0;
			track2Samples = getSamples( new Piano() );
		}
		
		public function getSamples( wav:ByteArray ):Array
		{
			return WavFormat.decode( wav ).samples;
		}
		
		public function processAudio( samples: Array ): void
		{		
			var s:Sample;
			var mergeSamples:Array;
			
			for( var i: int = 0 ; i < samples.length ; ++i )
			{
				mergeSamples = [];
				
				s = Sample( track1Samples[track1Position] );
				mergeSamples.push(s);
				
				s = Sample( track2Samples[track2Position] );
				mergeSamples.push(s);
				
				mergeAll( mergeSamples , samples[i] );
				
				track1Position++;
				if (track1Position > track1Samples.length-1) track1Position = 0;
				
				track2Position++;
				if (track2Position > track2Samples.length-1) track2Position = 0;
			
			}
		}
		
		public function mergeAll( sa:Array , bufferSample:Sample ):void
		{
			var r:Number = 0;
			var l:Number = 0;
			
			for( var i: int = 0 ; i < sa.length ; ++i )
			{
				r += Sample( sa[i] ).right;
				l += Sample( sa[i] ).left;
			}
						
			bufferSample.left = l;
			bufferSample.right = r;
		}
		
		public function reset():void
		{
		}
		
	}
}
zerlettino ist offline   Mit Zitat antworten
Alt 04-10-2007, 10:48   #13 (permalink)
faulancer
 
Benutzerbild von zerlettino
 
Registriert seit: Feb 2003
Beiträge: 281
Da mir der Ansatz viel besser gefällt als mehrere Soundobjete parallel einzusetzen würde ich das gerne weiterverfolgen.

Problem ist allerdings die Datenmenge die bei .wav Files aufkommt.

Es gibt einen Java Mp3 Decoder - kann jemand einschätzen ob man den in AS3 einigermaßen performant hinbekommen kann ? Der Source ist recht umfangreich- wäre viel Aufwand den umzuschreiben.

Kann man evtl. alternativ auch Sound-Assets aus swfs benutzen? Mit diesem Format sollte man doch leichter arbeiten können, oder?

Hast du da schon Erfahrungswerte Andre?

grüße
zerlettino ist offline   Mit Zitat antworten
Alt 22-04-2009, 15:28   #14 (permalink)
Neuer User
 
Registriert seit: Feb 2007
Beiträge: 32
Dauerton erzeugen

Hallo,

ich habe mir mal die API von Andre angeschaut. Super. Was ich nun möchte:
1. wie kann ich einen dauerton einer bestimmten Frequenz erzeugen
2. diesem Ton durch eine pauser eine bestimmten länge unterbrechen sodass es ein dauerpiepen wird.

Danke für hilfe

Martin
tengelman ist offline   Mit Zitat antworten
Alt 22-04-2009, 15:37   #15 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.271
Das ist nun völlig veraltet. Flash10 bringt native Soundunterstützung mit.

SampleDataEvent
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an



Alle Zeitangaben in WEZ +1. Es ist jetzt 16:31 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2012 Marc Thiele