Email Updates RSS Subscribe
Line

This blog is created and maintained by the technical team at Hook in an effort to preserve and share the insights and experience gained during the research and testing phases of our development process. Often, much of this information is lost or hidden once a project is completed. These articles aim to revisit, expand and/or review the concepts that seem worth exploring further. The site also serves as a platform for releasing tools developed internally to help streamline ad development.

Launch
Line

Hook is a digital production company that develops interactive content for industry leading agencies and their brands. For more information visit www.byhook.com.

Line

Ogg Vorbis Encoder + Decoder for Flash

Line
Posted on February 22nd, 2011 by Jake
Line

Hook Ogg Vorbis Library: Encoding/Decoding

*** POST UPDATED: Crackling issue fixed with “on the fly” decoder, please see below ***

So we finally have both halves of the equation! You can now, encode audio to the Ogg Vorbis format as well as decode it, all from the same library. A significant portion of the Decoding code was brought over from the Ogg Vorbis decoder on the Adobe Libraries page, written by Branden Hall of Automatastudios.com. Thanks Branden!

So a fair bit of the library was rearranged (from our previous version) to make it a touch easier to use. First up, the main example. This shows off most of the features in the library. Keep scrolling for the second example which demonstrates “on the fly” decoding.


Get Adobe Flash player

Download The Library and Examples
Download Just The library

If you have read our last post, you already know about some of the encoder features, but there have been a few changes, so we will go over each of them again.

The fist major change is there is now an OggManager class. This class is a wrapper for all of the alchemy bits, and is the main point of control for encoding and decoding Ogg Vorbis data. The quick answer is simply new up an instance of the OggManager, and then call .encode() or .decode(). From there you can listen for some events, and do what you need to do. For the long answer, lets start with the encoder portion of the library.

Encoder
The encoder works in 2 phases, first, the sound data is converted to a 44100, 16bit stereo pcm WAV format and is then encoded to Ogg Vorbis. The encoding process can take some time depending on how much data you are encoding. So this process is a fully asynchronous process. You can keep track of the progress by listening for the following events:
OggManagerEvent.ENCODE_BEGIN
OggManagerEvent.ENCODE_COMPLETE
OggManagerEvent.ENCODE_PROGRESS
OggManagerEvent.ENCODE_CANCEL
OggManagerEvent.WAV_ENCODE_BEGIN
OggManagerEvent.WAV_ENCODE_COMPLETE
OggManagerEvent.WAV_ENCODE_CANCEL
OggManagerEvent.WAV_ENCODE_PROGRESS

The encoding process can be canceled at any time by calling .cancel() on the OggManager instance. Please note that the process may not cancel right away, so please listen for the OggManagerEvent.ENCODE_CANCEL event to know when exactly the cancel has happened.

The method signature for the encode() method looks like this:

public function encode($rawBytes:ByteArray, $oggComments:OggComments=null, $oggQuality:Number=0.5, $wavLoopsPerYield=10, $vorbisLoopsPerYield:int=1, $progressNotifications:Boolean=true):void

$rawBytes is a byte array containg the raw flash sound data that is to be converted. $oggComments is an OggComments object that contains the tags/comments for the Ogg Vorbis file. These include things like Artist, Album, Title, etc… Next is the $oggQuality setting. This number ranges from -0.1 to 1 according to the xiph.org docs. 1 being the highest (largest file size, highest bitrate) and -0.1 being the lowest. I’ve played with different settings (as can you in the example above), and found that it is really amazing how low of a bitrate and how small of a file size you can get without sacrificing too much audio fidelity. $wavLoopsPerYield and $vorbisLoopsPerYield are performance settings. These basically decide how much time Alchemy gets to do the encode, before giving up its time slice to flash. The higher the number, the quicker the encode, but the slower flash will be. Lastly we have the $progressNotifications parameter. If this is true, progress notification events will be dispatched. Having this turned on, may slow the encode slightly, but without it, you won’t know how far along in the encode you are. You will however get BEGIN, COMPLETE and CANCEL events in either case. Currently the encoder still expects 44.1kHz, 16bit, Stereo data. Possibly in the future support for more formats will be implemented.

Decoder
The decoder can be used in two different ways. The first is where you can give it ByteArray full of Ogg Vorbis encoded bytes and after a few moments, it will give you back raw flash sound data. The other is to decode small chunks at a time, such as during the handling of a SAMPLE_DATA event when playing a sound. The example at the top of the post, is an example of how to decode the entire file all at once. The example below is how to decode the ogg file on the fly.


Get Adobe Flash player

Decoding the full file all at once is fairly trivial. You can simply call .decode() on the OggManager instance:

public function decode($oggBytes:ByteArray, $samplesPerLoop:int=2048, $delayPerLoopInMS:int=33, $progressNotifications:Boolean=true):void

The method signature breaks down as follows:
$oggBytes is the byteArray that contains your Ogg Vorbis encoded bytes from a file or wherever. The second parameter is an integer that controls how many bytes are decoded per loop. Just like the encoder, the decoding process is fully asynchronous. More bytes per loop speeds up the decode, but slows down flash. The third parameter controls how long to wait before kicking off another decode loop. If your decode loops are taking a long time, you will want to increase this number so that it doesn’t start to stack up decoding loops. Each chunk decode is handled by a timer, and the timer delay is set based on this parameter. The last parameter tells the OggManager to dispatch progress events for the decoding process or not. This is the same as with the encoder. Decoding may be faster if you do not dispatch progress events. BEGIN, COMPLETE and CANCEL events are always dispatched, regardless of this setting.

You can also keep track of the progress of the decode by listening for the following events:
OggManagerEvent.DECODE_BEGIN
OggManagerEvent.DECODE_COMPLETE
OggManagerEvent.DECODE_PROGRESS
OggManagerEvent.DECODE_CANCEL

The “On The Fly” decoding is very similar. (please have a look ath the DecodeOnTheFlyExample.as and .fla files) The main difference is you have to initialize the decoder before you start decoding. This is handled automatically if you are decoding the whole file at once but not if you are doing it on the fly.

To do that you can simply:

_oggManager.initDecoder(_oggBytes);

From there you can decode away, until you reach the end of the ogg bytes:

//Make sound
_sound = new Sound();
_sound.addEventListener(SampleDataEvent.SAMPLE_DATA, handleSoundData, false, 0, true);
_soundChannel = _sound.play();
private function handleSoundData(e:SampleDataEvent):void
{//handleSoundData
	var result:Object;
	var tmpBuffer:ByteArray = new ByteArray();
	result = _oggManager.getSampleData(_oggManager.dataPtr, NUM_SAMPLES, _oggManager.audioInfo.blockAlign, _oggManager.audioInfo.sampleMultiplier, tmpBuffer);
 
	if (tmpBuffer.length < NUM_SAMPLES * BYTES_PER_SAMPLE)
	{//reset
		trace("Reset");
		//Right now the only way to rewind is reseting the decoder
		_oggManager.initDecoder(_oggBytes);
		result = _oggManager.getSampleData( NUM_SAMPLES, tmpBuffer);
	}//reset
 
	tmpBuffer.position = 0;	
	while (tmpBuffer.bytesAvailable)
	{//feed
		//feed data
		e.data.writeFloat(tmpBuffer.readFloat());		//Left Channel
		e.data.writeFloat(tmpBuffer.readFloat());		//Right Channel
	}//feed
 
}//handleSoundData

The important part is the getSampleData line:

oggManager.getSampleData(NUM_SAMPLES, tmpBuffer);

The first parameter is how many flash sound samples you want back from the decoding. The second parameter is where those decoded bytes are stored. As you can see in the example code above we simply store the decoded bytes into tmpBuffer and then write those bytes back to the SAMPLE_DATA event. Its as simple as that. The one thing to be aware of however, is that seeking is not currently supported. So once you reach the end of the decode, you will need to initialize the decoder again to start back at the beginning of the ogg vorbis data. So depending on your needs you may want to cache this data as its decoded in a byte array for later use. But like I said, it kind of depends on what exactly you are doing with the data.

Please check out the Examples and feel free to just download the Wrapper and SWC.

In the next Alchemy installment we will go over getting an Alchemy Environment setup for Windows, and go through recompiling the sources for the SWC. From there we will talk about how to write your own Alchemy code, as well as other tips and tricks we have learned along the way.

Until next time you can get updates from our Facebook page:

Or you can follow me on Twitter:
Follow JakeCallery on Twitter

Good luck, and please let us know if you use this in a cool project, we would love to see it!

********** UPDATE **********
Good News Everyone
Good news everyone! I fixed the crackling issue with the “on the fly” realtime decoder. It should now function properly with clean (not clipped) sound. The issue turned out to be that we were dropping unused bytes. So now all of the bytes are fed to the SAMPLE_DATA event, instead of just the requested number of samples. The block alignment would sometimes force more bytes to be decoded than the exact number of requested samples. The code and downloads have been updated, and the code in the post has also been updated.
Good luck!

Line
67 Responses to “Ogg Vorbis Encoder + Decoder for Flash”
  1. Setup1337 says:

    Would it be possible to get in contact with you via some Instant Messenger?
    I have some audio crackling problems with certain .ogg-s that I’d like to talk to you about because they tend to break the synchronization in my music game. I have already tried sample rate adjusting and everything and the problem still persists. It also happens when using the OGG player that you’ve provided.

  2. Cool work! That was really awesome. Thank you very much for sharing this information. This post has been a tremendous help to me. I learned a lot.

  3. chedim says:

    Plz help %)
    Can i stream audio data with this encoder to server (i.e. Icecast)?

  4. timo says:

    So here we are, one year later ( http://labs.byhook.com/2011/02/22/ogg-vorbis-encoder-decoder-for-flash/comment-page-1/#comment-9871 ) Alchemy is now FlasCC, and a first official release version is out there :)

    I’m still very happy with the current OGG library, it’s working fine so far, however i’m wondering if you’re still interested in massaging this library into the official Alchemy/FlasCC release? I’ve tried it myself using the sources you’ve provided, but i was a little overwhelmed by the errors that were thrown (the C/C++ API seems to have changed a lot), i could fix some path issues, but unfortunately i don’t know C/C++ good enough to rewrite all the other stuff myself.

    Regards, Timo

    • Jake says:

      Hey Timo, really glad to hear the library is still working for you!

      I would really really like to convert it to FlasCC… My problem at the moment is of course time. I haven’t even looked at the new version yet, but from what you are saying, it sounds like it will be a fair bit of work. However it is high on my list if things to do

      • timo says:

        I know that feeling :) If I had more time I’d start learning C/C++ so that I could do it myself… actually it doesn’t look _that_ complicated, sharing domain memory/byte arrays, passing parameters and returning data, that isn’t rocket science, but I’m really missing some proper real world FlasCC tutorials, the reference really isn’t much of a help if you’re not familiar with C/C++ :(

        However, we’ll see what time will bring. Thanks for all your effort on this topic.

      • timo says:

        Well, I’m stuck. I’ve learned a little C/C++, I’ve managed to get some basic C AS3 ByteArray communication working (not enough to replace the Alchemy implementation tough), passing parameters works fine, compiling and archiving the Xiph library also works, but when it comes to compiling everything into an SWC, it fails with errors about undefined references, like for example “/tmp/randomname.o: error: undefined reference to ´_vorbis_info_init´”, and I have absolutely no clue what the problem might be :/

        Please let me know in case you or anyone elese have any idea what’s going wrong there :)

        • Philippe Raynaud says:

          Hi,

          I’ve the same problem, undefined reference to _vorbis_info_init using the oggvorbislib.a compiled by cross bridge. (on OSX)

          Do you solve it ?

          Thanks

  5. Hawk says:

    It will be perfect if we can get the oggComments out after decoding.

  6. Youngmin says:

    Is it possible to record audio and encode to ogg on the fly?

  7. JG says:

    First of all thank you for this amazing library. Very clean and easy to work with.

    I am able to record, playback uncompressed, and finally encode audio data from my mic. But if I take store the _oggManager.encodedBytes and try to play them later via _oggManager.decode() (or your decode-on-the-fly sample code) I get the following error during _oggManager.initDecoder():
    [Fault] exception, information=RangeError: Error #1506: The specified range is invalid.

    Is there a different method I should use to load/play a ByteArray that has never been saved to a user’s hard drive?

    • Jake says:

      @JG, my initial guess would be that you need to set oggBytes.position = 0 before passing it into the decoder

      • JG says:

        Wow thanks for the superfast reply.
        Setting the position was one of the first things I tried as well.

        I’ve spent a lot of time debugging but I guess my question is *should* I be able to supply the decoder with the exact bytes that _oggManager.encodedBytes supplies me? If that theoretically should work, I can strip down the code for a test case.

        The only other thing I am considering at this point is if the C library gets instantiated at multiple points, over multiple instances through the process.

        Thanks again and really this is an amazing utility.

        • Jake says:

          @JG, no problem, glad you like the lib :)

          I just tried recording from the mic, doing an encode, and then doing a full decode of the _oggManager.encodedBytes and playing those decoded bytes and it seems to work. As I get time today I will try the decode on the fly method.. I get the feeling you are right with calling init() more than once might be messing up the pointer to the data… I will see what I come up with and get back to you here…

          Thanks much for the interest!

        • Jake says:

          @JG, alrighty, its working for me, and I think I know what probably happened..
          I’m guessing you were passing in .encodedBytes directly to the initDecoder()… when initDecoder() is called it blows away the encoded bytes, so you need to duplicate the encodedBytes bytearray first.. This should get you all fixed up, please let me know how it goes..

          private function handlePlayEncodedBytesClick(e:MouseEvent):void
          {//handlePlayEncodedBytesClick
          _oggManager.encodedBytes.position = 0;
          _oggBytes.length = 0;
          _oggBytes.position = 0;
          _oggBytes.writeBytes(_oggManager.encodedBytes, 0, _oggBytes.length);
          _oggManager.initDecoder(_oggBytes);
          _onTheFlySoundChannel = _onTheFlySound.play();
          }//handlePlayEncodedBytesClick

          and the handleSoundData is the same:
          private function handleSoundData(e:SampleDataEvent):void
          {//handleSoundData
          var result:Object;
          var tmpBuffer:ByteArray = new ByteArray();
          result = _oggManager.getSampleData(NUM_SAMPLES, tmpBuffer);

          if (tmpBuffer.length < NUM_SAMPLES * BYTES_PER_SAMPLE)
          {//reset
          trace("Rewind");
          //Right now the only way to rewind is reseting the decoder
          _oggManager.initDecoder(_oggBytes);
          result = _oggManager.getSampleData(NUM_SAMPLES, tmpBuffer);
          }//reset

          tmpBuffer.position = 0;

          while (tmpBuffer.bytesAvailable)
          {//feed
          //feed data
          e.data.writeFloat(tmpBuffer.readFloat()); //Left Channel
          e.data.writeFloat(tmpBuffer.readFloat()); //Right Channel
          }//feed

          }//handleSoundData

  8. Alexandr says:

    Hi! You make a great thing! It’s exactly what I need right now!

    But I have some trouble. When I encode recorded voice output file plays with double speed. Something going wrong at the “WAVWriter step”. What am I doing wrong?

    • Jake says:

      I’m guessing you are passing it a mono file, it needs to be stereo. If its mono, it sounds twice as fast because its processing twice as many bytes per cycle, normally left/right of a stereo file.

  9. timo says:

    Hey there,

    first of all thank you very much for your hard work on this one :)

    I’m wondering if you have considerd wrapping this up in a native extension for Adobe AiR? And are there any plans to update the library with the upcoming commercially supported version of Alchemy?

    http://blogs.adobe.com/flashplayer/2011/09/updates-from-the-lab.html

    Regards, Timo

    • Jake says:

      Hey Timo,
      First off, you are very welcome :)
      Second, I’ve played around with native extensions a bit, and unfortunately I don’t think this will be as easy as wrapping the current code base. For instance I would need to make a version for windows, android, ios, etc. For windows I think it woudn’t be terrible since the source is in C already, but I would need to port it to Java and ObjectiveC for the others, and that doesn’t sound like fun to me :) So the chances of me making a native extension out of this is pretty slim.
      Now on the other hand, I would be more than willing to massage this into “official” alchemy when its available.

      Thanks again for the interest!

      • timo says:

        I can totally feel with you, a native extension seems to be too much work :) And when the final Alchemy version really brings a significant performance boost (it’s already not that bad) and up to 75% code reduction, well, guess that would make the performance gap to a native extension more or less negligible. Can’t wait to see how it performs :)

        Regards, Timo

  10. Droqen says:

    Can I use this to play multiple ogg files at once?

    I don’t often play around with sound decoding – I hope I can figure it out! I’ve been playing around far out of my depth.

    • Droqen says:

      Also, this is absolutely fantastic. Thanks for making this; I’m finally wrapping my head around this whole thing AND it’s working! I can’t say the same for the myriad of other oggflash libraries I’ve struggled through before remembering I’d already downloaded this one a long time ago.

  11. Jake says:

    @vlad, I noticed the same thing, while I’m not completely sure, I think its the pre-building of the encoder’s lookup tables that takes the time. Its either that or the fact that there is a lot more bytecode to read in due to the fairly heavy extra encode alchemy code… Unfortunately like I said, I’m not completely sure…

    • vlad says:

      Wow that was a fast reply!

      I was considering using the library in a project, but that lag really kills the user experience. In your examples you load the library on init – I tried to load it only when it’s actually needed, but the delay is still there.
      If loading the library takes that long, do you think there is a way to mask it and still retain some cycles for the UI (the way the encoding works)?
      I am not a flex developer so I really appreciate your thoughts on this.

      Thanks!

      • Jake says:

        Hey Vlad, I just wanted to let you know I’ve haven’t forgotten about you, just got really busy all of a sudden. I haven’t looked at the code in quite some time, so I can’t remember exactly where the Clib .init() is called, but you could try not calling that right away and see if that helps… I think in OggEncoder.as there is something like this:
        //Setup the alchemy library
        _loader = new CLibInit;
        _lib = _loader.init();
        You could try pushing that off until a later time, that might be where the pause happens…
        Please let us know if that helps…

  12. sm says:

    Great library. The encode seems to hang for me and does not process asynchronously.

  13. bram says:

    Hey Jake,

    finally found some time to play around with this…

    I’m encoding ogg’s and I’m getting weird results:

    sometimes to wav encode “just” stops, sometimes it all works fine, sometimes I get:

    RangeError: Error #1506: The specified range is invalid.
    at cmodule.hookOggVorbisLib::FSM_imalloc$/start()
    at cmodule.hookOggVorbisLib::FSM_pubrealloc/work()
    at cmodule.hookOggVorbisLib::CRunner/work()
    at MethodInfo-2141()
    at flash.utils::Timer/_timerDispatch()
    at flash.utils::Timer/tick()

    Any idea? I was wondering what happens if the defined timers spend more time in onTimer than their delay is set to. Can timers be broken this way?

  14. Hi Jake

    Great work you’ve done here. I’ve been looking at various ogg vorbis implementations these days for a project which requires streaming encrypted audio files, and yours seems to be the most advanced :)

    The current solution we use is based on the Alchemy Library from Adobe : we have an encrypted ogg file, and an EncryptedInputStream class that decrypts only the necessary bytes on demand (for performance reasons). I plugged this into Adobe’s library, and it works pretty well, except for a few clicks every now and then…

    I tried using your library, but the code base seems quite different now, and requires using ByteArrays to handle the data. Decrypting our audio files takes more than 300ms on my machine (so probably much more on lower end PCs), and so we cannot decrypt the whole file before we start playing it. I did not manage to import your library/test files in our current Flash Builder 4.5 project (I’m pretty new to Flash Builder, so I probably did something wrong).

    Do you know if there’s a chance that the bug you fixed for the audio clicks is the same one I currently have using the other library ? (note : I tested the audio file in your demo app and it plays fine) If that’s the case, is there any chance this fix could be backported into the other lib (or any hints as to how to fix it ?).

    Thanks,
    Gregory

    • Jake says:

      Hey Gregory, I’m not sure if the bug I had is the same as the one you are experiencing… I haven’t tried any of this with actual streaming audio (like from a shoutcast station or something), which turns out to be a very different animal.

      I have a feeling that the clicking you are getting is not caused by the same issues that we were having, but I might be misunderstanding what you are trying to do.

      We were getting clicking because when the byte block alignment was off, we were actually decoding slightly more data. Then when I went to play it back I was skipping the “extra” data… so when the next round of decoding happened, we had moved past the extra data, but never played it, which resulted in a click/pop.

      However if you are just more or less decoding from a file, in a similar manor to our “decode on the fly” method, then you might be able to just use that. Its only a few lines of code to get that done. Have a look at the source for the DecodeOnTheFlyExample.as, that might get you there.

      One other thing to consider, is that if you are decoding the smallest number of samples possible (2048) each round, its possible that the decoding is taking too long (greater than the 43ms 2048 samples lasts) and the soundcard is not being feed quickly enough. That could also produce a click/pop. You might want to try decoding more at a time to keep the buffer full such ase 8192 samples at a time.

      • Wow, that was fast :)

        I suspected that the problem could come from insufficient speed, but I tried with a pure ogg file (ie, not encrypted) and I have the exact same click at the exact same time (for a specific file). I’m guessing that if it was a speed issue I would see a difference (either no click on a fast already loaded file, or at least at a different moment).

        When I traced the decoded data I noticed that every once in a while it had decoded more than needed, but that happens pretty often and without any click sound. It seems to use all the extra data anyways.

        Changing the buffer size doesn’t seem to have any effect (except when I set it too low).

        Just to clarify things out, I was talking about Stream more as the Java Streams than ActionScript ones (ie, streaming data from a file, or from any data source, not just from a URLStream). The encrypted files we have are stored on the user’s HD.

        Thanks for your answer, I’ll probably work on something else for a few days and come back to it later. My best option is probably to use your updated version. I just need to figure out why the app freezes (completely) when it’s loading the library (waited for a few minutes, nothing came up). I’ll get back to you in a few days if I can’t get it up and running :)

        Thanks again,
        Gregory

        • Jake says:

          If you read the rest of the comments, others have had that same freezing issue, It seems to be caused by having different versions of the flexsdk installed and running under a different adl. Does it freeze only in the adl or even when packaged as an app? Check out what Tim, Marko, and Oliver did to fix it (in the comments)
          Also please keep us updated on your progress :) I would love to know the causes for the issues you are having…

          • I’ll do some testing soon :) When I saw it just hanged, I didn’t try anything special, just reloaded it to see if it happened again ^^ I was using the debug mode, so it crashed in the ADL. Haven’t tried packaging the app yet.

            I read the other comments, but they don’t quite seem to apply to my case : this is the first install I do of FlashBuilder, so I probably don’t have different flexsdk installed on my computer (unless FlashBuilder installs different flavors, I guess…).

  15. Jake says:

    Hey Tom, just wanted to let you know that the crackling issue has been fixed, and the downloads have been updated. So you should be all set now.

  16. Bram de Jong says:

    Hi there Jake,

    is there any chance that you will host this work on a public repository site like google code or github? It would be very interesting to use the realtime decoder on freesound.org, just to get around the silly “non-perfect-looping” of mp3.

    For my private work this is also rather interesting!!

    I did notice that the on the fly method does some clipping while playing (which might be due to CPU usage?).

    Anyway, I’d be interested to even help messing with the library, but that it would need to be somewhere public I think…

    greetings,

    – Bram

    • Jake says:

      Ah, yes indeed… problem is I have to write a post to go with it :) And we have been swamped lately, so I haven’t gotten to it yet. But I assure it its coming :)

  17. mack says:

    Is there way to store this file on server not in local, so it’s available for user once’s he store..

    • Oliver says:

      What happens with the data isn’t the libraries bussiness, so that’s not really the best place for such questions, you’d better discuss things like that in a general Flash/ActionScript forum. That beeing said, what happens with the produced data is totally up to you, if you want it to be stored on a server, then simply send it to a server. Examples: http://www.google.com/search?hl=en&q=as3+bytearray+to+server

      Best
      Oliver

  18. tim says:

    Awesome! This is exactly what i was looking for in order to be able to avoid using external lilbraries like FFmpeg or SoX. However i’m wondering about the terms of usage since there are no license information supplied with the package?

    Regards, Tim

    • Jake says:

      Doh! I knew I forgot something… I have updated the .zip files (using the same links above) that now include licensing info. The short answer is its pretty much unrestricted… Our code is under the MIT license in this case, the Adobe WavWriter code (which has been modified by us) is basically unrestricted, other than the fact that you can’t use Adobe’s name for advertising purposes, and the XIPH stuff is essentially unrestricted. As usual for these kinds of things there are no warranties and its uses on an “AS IS” basis. Check out the License.txt file in the new zips for specifics.

      Now I’m not saying we wouldn’t love a mention, but its totally not required :)

      If you get something running, we would love to see it!

      • Tim says:

        Thanks for the info, ofcourse everyone will be mentioned when i’m using the library :)

        Unfortunately i’m now facing the same problems as Marko Tomic did, when testing in a bigger AiR app using ADL it completely hangs when the Alchemy stuff is initialized. It works with ADL when using a clean AiR project and Flex SDK 4.5 (v4 doesn’t do it for me), and it also works when running the actual installed AiR app (with both, v4 and v4.5 SDK)… guess i’ll have to spent the next few nights with a LOT of trial and error type of debugging :D

        Regards, Tim

        • Jake says:

          Well, booo… I’m assuming you are building in debug mode, if you try in release mode do you get the same result? It might also be worth splitting the lib into two swcs, using the Encoder and Decoder separately.. which would mean using our encoder (from past posts) and the Adobe decoder… I’m starting to think its a stack size limitation, but at the moment I can’t be sure. At the moment, we are a bit swamped so I can’t really look into it more right now, but if you find anything, I would love to know, and I’ll update the post…

        • Jake says:

          Ah, also forgot to ask what your build environment is like, FlashDevelop/FDT/FlashBuilder/Flash IDE? And are you using the AIR for Android stuff?

          • Tim says:

            I’m using FlashDevelop 3.3.4, the app is intended for desktop only, and i’m testing on Windows 7 x64. Debug or Release, doesn’t make any difference, same with the encoder only library.

            I’ll see if rebuilding the app piece by piece sheds any light on the problem.

            Regards, Tim

        • Oliver says:

          I had the same problem, updating to the latest 2.6 AiR SDK solved it for me, you may want to give it a try in case you are not already using it. Initialization still takes quite some time when using ADL, something between 4 and 6 seconds, but then it works just fine.

          Best
          Oliver

          • Tim says:

            Ah, silly me, i forgot to update the AiR SDK in the Flex 4 folder, i only copied it to the 4.5 one… sorry for the trouble :)

            Regards, Tim

          • Jake says:

            Yey! Glad its working now, I was starting to get worried… Thanks for keeping us updated, and its no trouble at all!

  19. tom says:

    Um, I think there’s something wrong with your player. The sound plays but it’s got pops and crackles. Running the ‘incubator’ FP11 (all other audio has been fine).

    • jake says:

      Do you have the same issue with both examples? I’ve seen that on one computer with an integrated soundcard. It sounded like volume clipping. If you are having that issue you can try turning down the volume on the soundtransform.

      • Jake says:

        I’ve confirmed it on a second machine with the second example. It seems to only happen during the “decode on the fly” way of using the lib. So I don’t think its a decoding problem as much as either a byte boundary or sound clipping issue in the AS3 code. At the moment, I don’t have the time to investigate, but if you do, I would appreciate hearing about anything you find. Thanks!

  20. Marko Tomic says:

    Great post. I’m running this in Flash builder and it works fine as a Flash Project. However, the app hangs when I run this as Adobe AIR project. ADL starts up and it freezes. Any idea why?

    Thanks

    • Jake says:

      Hey Marco, I have tried, the Encoder code and the Decoder code seperatly through the adl, but I have not tried this current version of the library. The others worked, ok, but I will give this one a whirl over the weekend and see if I can spot something. The short answer is that it should work, but I haven’t tried this version.

      I’ll post a reply here with what I find.

      Thanks!

    • Jake says:

      Ok, so I had a minute to try this out:
      http://labs.byhook.com/oggvorbislib/AirOggTest.zip

      It does hang the app for a second, but then it continues on ok for me, very similar to what happens to the flash examples in the post. It seems to happen when .init() is called on the Alchemy lib. Unfortunately I think it is just what happens when a library this big is loaded. But this means you can probably put off the delay until you need the Library, but just not newing up the OggManager until needed. Good luck!

  21. Kelly James says:

    This is amazing. Thank you!

  22. Karl Macklin says:

    Hey!
    Your blog is awesome.

    *does the “we’re not worthy” chant from wayne’s world*

  23. Tariq says:

    Me again :)
    I’ll try the decoder out tonight. It looks perfect for what I need ;)
    Thanks again, its a HUGE help!

    • Jake says:

      haha awesome, let us know how it goes!

      • Tariq says:

        Works great :) encodes, decodes, the whole lot.
        But…I played with the code and got myself stuck.
        After the first recording, everything is fine, but when I stop recording the second time I get this error:

        TypeError: Error #1009: Cannot access a property or method of a null object reference.
        at ValueTracker/get()
        at CAS3ValTypemap/fromC()
        at MethodInfo-1292()
        at cmodule.hookOggVorbisLib::FSM_readba/work()
        at cmodule.hookOggVorbisLib::CRunner/work()
        at MethodInfo-1238()
        at flash.utils::Timer/_timerDispatch()
        at flash.utils::Timer/tick()

        I must be passing something through the hookOggVorbisLib doesn’t like, but when I check, its basically the same types of variables. Do I have to re-initialise something inside the hookOggVorbisLib ? Thanks.

        • Jake says:

          Hey Tariq, I would say make sure that none of the values passed in are NULL, also make sure that any of the bytearray’s passed in have their position set back to 0 before making the alchemy call. myByteArray.position = 0; Also if you make a new byte array to pass in and are “Decoding” you will probably have re-init the decoder (can’t remember the call exactly, I don’t have the code in front of me, but the call is obvious from the name)
          Good luck!

  24. [...] This post was mentioned on Twitter by karannnnnnnnnnn3, Jake Callery. Jake Callery said: New version of our @Adobe #Alchemy Ogg Vorbis Libray for flash is up: http://bit.ly/eV3kCr Encoding and Decoding all in one library! [...]


Leave a Reply

*

Line
Line
Pony