Question

I'm working on a virtual piano keyboard that processes imported mp3 sound samples. I've come to a solution with this question, but as I run this test code below, the sound loops its last data chunk of each sound source forever, and obviously, I want it to stop at the end of the extracted sound data. The same happens with any extracted sample data, I don't even have to mix it. I added a dynamically drawn graphic waveform so you can visually check what happens. This is my first time using the ByteArray class, so I don't know how to solve this issue.

import flash.media.Sound;
import flash.utils.ByteArray;
import flash.geom.Point;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.events.MouseEvent;

var t0:Sound = new Sound(new URLRequest("5_C.mp3")); //sound imported
var t1:Sound = new Sound(new URLRequest("5_E.mp3")); //other sound imported
//var t0:Sound = new C4(); //sound in library
//var t1:Sound = new E4(); //other sound in library
var t0p:Point = new Point();
var t1p:Point = new Point();
var t0a:ByteArray = new ByteArray();
var t1a:ByteArray = new ByteArray();
var mix:Sound = new Sound();

var spr:Sprite = new Sprite();
addChild(spr);
spr.y = 10;
var lx:Number = 0;
var ly:Number = 0;
spr.graphics.lineStyle(1,0,1,true);

mix.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);

stage.addEventListener(MouseEvent.CLICK, mce);
function mce(e:MouseEvent) {
    mix.play();
}

function onSampleData(e:SampleDataEvent):void {

    t0a.position = 0;
    t1a.position = 0;

    t0.extract(t0a, 3072);
    t1.extract(t1a, 3072);

    t0a.position = 0;
    t1a.position = 0;

    for(var i:int = 0; i < 3072; i++) {

        t0p.x = t0a.readFloat();
        t0p.y = t0a.readFloat();
        t1p.x = t1a.readFloat();
        t1p.y = t1a.readFloat();

        var tmp:Point = new Point(Math.max(Math.min(t0p.x + t1p.x, 1), -1), Math.max(Math.min(t0p.y + t1p.y, 1), -1));

        e.data.writeFloat(tmp.x); // left
        e.data.writeFloat(tmp.y); // right

        if (lx > 549) {
            lx = 0;
            ly += 10;
            if (ly > 399) {
                spr.graphics.clear();
                ly = 0;
                spr.graphics.lineStyle(1,0,1,true);
            }
            spr.graphics.moveTo(lx, (tmp.x + tmp.y) * 4 + ly);
        } else {
            spr.graphics.lineTo(lx, (tmp.x + tmp.y) * 4 + ly);
        }
        lx += 0.05;

    }
}

There must be a very simple solution for this, I just don't have experience with handling raw data, so I'd be really thankful if you could help me out with anything.

Was it helpful?

Solution

Okay, I've come up with a solution a few days ago, I just didn't have time to post it here.

An easy way to calculate a sound's ByteArray sample length is samplesLength = sound.length * 44.1;.

This is because a sound displays its length in milliseconds, which are 1000 stereo sample-pairs per second, and the sampling resolution for sounds in flash is 44100 Hz (also sample-pairs per second), so there are 44.1 sample-pairs rendered over a brief millisecond.

Also, a sample is a 32-bit Float value, and a sample-pair is 64 bits (8 bytes) long, so if I'm correct, it's samplesLength = soundExtract.length / 8;.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top