Zurück   Flashforum > Flash > ActionScript > ActionScript 3

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 20-02-2009, 20:39   #1 (permalink)
Neuer User
 
Registriert seit: Nov 2008
Beiträge: 14
ByteArray zu Sound?

Ich seh grad nicht wie, aber ist es möglich aus einem ByteArray oder genauer einen schon geladenen Datenblock in ein Soundobjekt umzuwandeln?

Hintergrund:
Ich möchte gerne gepackte Resourcen (also als ZIP) nachladen, darunter auch Sounddateien. Nun habe ich nach Laden nur die reinen Daten.
Gibt es einen Weg daraus ein Sound-Objekt zu machen ?

MfG Lotes
Lotes ist offline   Mit Zitat antworten
Alt 21-02-2009, 10:58   #2 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.271
Native nicht, aber mit der Popforge library gehts.

Seit Flash10 gibt es das SampleCallback des SoundObjektes. Das ist wesentlich flexibler.
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 21-02-2009, 12:45   #3 (permalink)
Neuer User
 
Registriert seit: Nov 2008
Beiträge: 14
Danke, werde ich mir mal anschauen ;-).
Lotes ist offline   Mit Zitat antworten
Alt 23-02-2009, 01:22   #4 (permalink)
Neuer User
 
Registriert seit: Nov 2008
Beiträge: 14
So hab's mir angeschaut :-).
Da haste ganz clever ne SWF-Datei Byte für Byte samt Sounddaten geschrieben und geladen.
Ich hab ein bissel recherchiert. Gute Links zum Dateiaufbau einer SWF sind:
http://www.swfmill.org/
http://www.half-serious.com/swf/format/index.html

Ich werd mir jetzt nen Fetzen AS3 zusammenklappern, der mir MP3-Daten zu Sound lädt. Bei Erfolg poste ich den Code-Schnipsel hier rein :-).
Lotes ist offline   Mit Zitat antworten
Alt 23-02-2009, 18:25   #5 (permalink)
Neuer User
 
Registriert seit: Nov 2008
Beiträge: 14
So fertig. Der Code ist stark angelehnt an Popforge.


Folgende Datei ist davon entwendet ;-): swf.bin
Sie ist ein Teil der SWF-Datei, die zu Laufzeit fertiggeschrieben und aus der die Sounddatei dann geladen wird.
Code:
[Embed(source = "swf.bin", mimeType = "application/octet-stream")] 
static private const SoundSWF: Class;
Natürlich ist auch etwas Eigenleistung dabei . Folgender Code liest die MP3-Daten und liest die Anzahl der Samples, sowie die Bit- und Samplerate aus. Bei den Eigenschaften "Stereo" und "16bit" weiß ich nicht wie ich die abfragen soll ~~~. Aber es geht erstmal so.
Code:
                    private function analyzeMP3Data(data: ByteArray): Object {
			//see http://www.mp3-tech.org/programmer/frame_header.html
			//constants
			const bitratesV1L1: Array = new Array(0,32,64,96,128,160,192,224,256,288,329,352,384,416,448,0);
			const bitratesV1L2: Array = new Array(0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0);
			const bitratesV1L3: Array = new Array(0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0);
			const bitratesV2L1: Array = new Array(0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0);
			const bitratesV2L23: Array = new Array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 114, 160, 0);
			const sampleratesV1: Array = new Array(44100,48000,32000, 0);
			const sampleratesV2: Array = new Array(22050,24000,16000, 0);
			const sampleratesV25: Array = new Array(11025,12000,8000, 0);
			
			//variables
			var rslt: Object = new Object();
			var c: int;
			
			var mpegVersion: int;
			var layer:       int;
			var bitrate:     int;
			var samplerate:  int;
			var padding:     int;
			var framesize:   int;
			var frames:      int = 0;
			
			var samplerateArray: Array;
			var bitrateArray: Array;
			
			//go to the first frame
			while ((data.position < data.length) && (data.readByte() != -1));
			
			//read version byte
			c = data.readByte();
			mpegVersion = (c >> 3) & 3; 
			layer       = 4 - (c >> 1) & 3;
			if (mpegVersion == 1 || layer == 4)
				throw new Error("Bad formated version.");
			
			//choose rate data fields
			switch(mpegVersion) {
				case 0:
				case 2:
					if(layer==1)
						bitrateArray = bitratesV2L1; else
						bitrateArray = bitratesV2L23;
					if(mpegVersion == 0)
						samplerateArray = sampleratesV25; else
						samplerateArray = sampleratesV2;
					break;
				case 3:
					switch(layer) {
						case 1: bitrateArray = bitratesV1L1; break;
						case 2: bitrateArray = bitratesV1L2; break;
						case 3: bitrateArray = bitratesV1L3; break;
					}
					samplerateArray = sampleratesV1;
			}
			
			//read bitrate/samplerate byte
			c = data.readByte();
			bitrate     = (c >> 4) & 15;
			samplerate  = (c >> 2) &  3;
			
			//count frames
			do {
				padding = (c >> 1) &  1;
				
				frames++;
				framesize = 144000 * bitrateArray[bitrate] / samplerateArray[samplerate] + padding;
				data.position += framesize - 3;
				if(data.position < data.length) {
					data.readByte(); //frame start
					data.readByte(); //version
					c = data.readByte();
				}
			} while (data.position < data.length);

			rslt.samples = frames * samplerateArray[samplerate];
			rslt.samplerate = samplerateArray[samplerate];
			rslt.bitrate    = bitrateArray[bitrate];
			rslt.is16bit    = true;
			rslt.isStereo   = true;

			return rslt;
		}
Folgender Code ist aus der Soundfactory aus Popforge entnommen/nachempfunden. Dabei wird zuerst die MP3 unter die Lupe genommen und einige Daten mit der obigen Funktion extrahiert und hier wiederverwendet. Bei der Bitrate wird derzeit nur 128kbit/s unterstützt, da ich die Bitmuster der anderen 15 noch nicht zugeordnet habe .
Im wesentlichen wird hier die SWF mit der MP3 aufgebaut und geladen .
Code:
		public function loadBytes(data: ByteArray, name: String): void {
			var properties: int = 0;//0x2F
			var samples: int    = 0;
			var mp3Props: Object;
			
			//====> analyze data <====//
			try {
				mp3Props = analyzeMP3Data(data);
			
				//samples
				samples = mp3Props.samples;

				//audio properties
				switch(mp3Props.samplerate) {
					case 11025: properties |= 1 << 2; break;
					case 22050: properties |= 2 << 2; break;
					case 44100: properties |= 3 << 2; break;
					default:
						throw new Error("Unsupported sample rate");
				}
				
				switch(mp3Props.bitrate) {
					//...15 other rates missing...
					case 128: properties |=  2 << 4; break;
					default:
						throw new Error("Unsupported bitrate");
				}

				if (mp3Props.is16bit)
					properties |= 2;
				if (mp3Props.isStereo)
					properties |= 1;
			} catch (e: Error) {
				dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, e.message))
			}
			//set name
			_url = name;
			
			//====> build SWF file <====//
			//set properties
			
			//Header + needed tags
			var swf: ByteArray = ByteArray(new SoundSWF());
			swf.endian = Endian.LITTLE_ENDIAN;
			swf.position = swf.length;

			//Tag: DefineSound
			swf.writeShort(0x03BF);             //tagID for DefineSound (long header)
			swf.writeUnsignedInt(data.length+7);//tag length (+7 -> meta information)
			swf.writeShort(1);                  //object ID
			swf.writeByte(properties);          //sound properties
			swf.writeUnsignedInt(samples);      //samples count
			swf.writeBytes(data);               //sound data

			//Trailer
			swf.writeUnsignedInt(1 << 6);       //EOF
			
			//overwrite length field
			swf.position = 4;
			swf.writeUnsignedInt(swf.length);

			//====> load (sound) SWF file <====//
			var onSWFLoaded: Function = function( event: Event ): void {
				_snd =	Sound( new ( loader.contentLoaderInfo.applicationDomain.getDefinition('SoundItem') as Class )() );
				dispatchEvent(new Event(Event.COMPLETE));
			}
			try {
				var loader: Loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSWFLoaded);
				loader.loadBytes(swf);
			} catch (e: Error) {
				dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "No valid sound data."))
			}
		}
Das Eventrumdisgepatche kann man sich bei Bedarf sparen, find ich aber wichtig.

Danke für Popforge, André.
Lotes ist offline   Mit Zitat antworten
Alt 23-02-2009, 19:41   #6 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.271
Sehr schön. Die MP3 Erweiterung kannst du noch um den Lame-Tag erweitern, dann sind MP3s auch loopbar (wenn Lame encodiert).
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com
André Michelle ist offline   Mit Zitat antworten
Alt 23-02-2009, 20:48   #7 (permalink)
Neuer User
 
Registriert seit: Nov 2008
Beiträge: 14
O.o Lame-Tags sagen mir gar nichts... und Google sagt dazu auch nichts :-/.
Hast du ein paar gute Links dazu? Derzeit brauche ich Loops nicht, aber vielleicht kommt das ja noch .

Geändert von Lotes (23-02-2009 um 20:58 Uhr) Grund: Grammatik=Käse
Lotes ist offline   Mit Zitat antworten
Alt 27-02-2009, 03:02   #8 (permalink)
Neuer User
 
Registriert seit: Nov 2008
Beiträge: 14
Nachtrag:
Das mit den 15 anderen Formaten ist Blödsinn xD.
An entsprechender Stelle bedeutet 2<<4 einfach: "Format ist MP3" :-).
In der SWF-Spezifikation Seite 201 steht's muhahaha.
(kann man ja nicht so stehen lassen hier ;-))
Lotes ist offline   Mit Zitat antworten
Alt 27-02-2009, 07:36   #9 (permalink)
[+]
 
Benutzerbild von André Michelle
 
Registriert seit: Dec 2002
Ort: cologne
Beiträge: 2.271
Ich denke, wenn das Bit auf MP3 steht, dann liest der Flashplayer alle weiteren Information aus den MP3 Headern (Samplingrate, Bitrate).

Lame ist ein MP3 Encoder, der in einem speziellen Tag Encoding-Informationen einschleust, die normalerweise unter den Tisch fallen. Damit lassen sich MP3 beim Decodieren zB. wieder auf die Originallänge kürzen, um sie zB. zu loopen.

http://gabriel.mp3-tech.org/mp3infotag.html
__________________
aM

blog | laboratory | tonfall | processing

Audiotool.com

Geändert von André Michelle (27-02-2009 um 07:37 Uhr)
André Michelle ist offline   Mit Zitat antworten
Alt 27-02-2009, 12:26   #10 (permalink)
Neuer User
 
Registriert seit: Nov 2008
Beiträge: 14
Zitat:
Zitat von André Michelle Beitrag anzeigen
Ich denke, wenn das Bit auf MP3 steht, dann liest der Flashplayer alle weiteren Information aus den MP3 Headern (Samplingrate, Bitrate).
Die Bitrate ist egal und die Samplingrate muss angegeben werden, sonst wird es nicht abgespielt. Das 16bit-Flag wird bei MP3 ignoriert und scheinbar auch das Stereo-Flag. Es ist also nur die Samplingrate und das MP3-Flag entscheidend (und natürlich die Anzahl der Samples).
Lotes ist offline   Mit Zitat antworten
Alt 15-08-2009, 01:38   #11 (permalink)
muh
 
Benutzerbild von Janoscharlipp
 
Registriert seit: Apr 2002
Ort: Freiburg / Stuttgart
Beiträge: 4.338
Um das nochmal auszugraben:
Das 16 Bit / 8 Bit Flag *muss* auf 1 gestellt werden (also 16 Bit), damit der Sound korrekt abgespielt wird.

Um die Informationen aus den MP3-Daten auszulesen kann man mp3infoutil verwenden. (nicht perfekt, aber recht brauchbar)

Nicht so ganz klar ist mir die Berechnung vom SampleCount, insbesondere bei VBR bin ich unsicher, was die richtige Lösung ist.
Einfach frameCount * 576 (wie man es sonst so als Angabe findet), schneidet am Ende des Sounds ein Stückchen ab
Momentan nehme ich die Zahl einfach noch mal zwei, (sollte reichen ) scheint keine Fehler auszulösen (die Tag-Length ist ja auch noch da) aber ist natürlich nicht die feine Art.
__________________
»Carpe diem«, sagte der Graf. (Terry Pratchett: Ruhig Blut!)
Janoscharlipp 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:19 Uhr.

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


Copyright ©1999 – 2012 Marc Thiele