lundi 25 mai 2015

Audio recorded file corrupted issue in Actionscript

I recorded voice samples from my microphone using Adobe Flash Builder 4.6 / AIR, voice recorded successfully. I first converted voice data(byte array) to base64 format in actionscript then I converted that base64 data to WAV file using my PHP code. but that WAV file throw file corrupted issue in RiffPad.

RIFFPad is a viewer for RIFF formatted files like WAV, AVI.

// -- saves the current audio data as a .wav file
    protected function onSubmit( event:Event ):void {
        alertBox.show("Processing ... please wait.");

        stopPlayback();
        stopRecording();
        playBtn.enabled = recordBtn.enabled = submitBtn.enabled = false;
        var position:int = capture.buffer.position;
        var wavWriter:WAVWriter = new WAVWriter()
        var wavWriter1:WaveEncoder = new WaveEncoder()
        wavWriter.numOfChannels = 1;
        wavWriter.samplingRate = 22050;
        wavWriter.sampleBitRate = 16; 
        var wavBytes:ByteArray = new ByteArray;
        capture.buffer.position = 0;
        wavBytes = wavWriter1.encode( capture.buffer, 1, 16, 22050);
        capture.buffer.position = position;
        wavBytes.position=0;
        submitVoiceSample(Base64_new.encodeByteArray(wavBytes));
    }

WAV Data Writer function:

/**
     * 
     * @param samples
     * @param channels
     * @param bits
     * @param rate
     * @return 
     * 
     */     
    public function encode( samples:ByteArray, channels:int=1, bits:int=16, rate:int=22050 ):ByteArray
    {
        var data:ByteArray = create( samples );

        _bytes.length = 0;
        _bytes.endian = Endian.LITTLE_ENDIAN;

        _bytes.writeUTFBytes( WaveEncoder.RIFF );
        _bytes.writeInt( uint( data.length + 44 ) );
        _bytes.writeUTFBytes( WaveEncoder.WAVE );
        _bytes.writeUTFBytes( WaveEncoder.FMT );
        _bytes.writeInt( uint( 16 ) );
        _bytes.writeShort( uint( 1 ) );
        _bytes.writeShort( channels );
        _bytes.writeInt( rate );
        _bytes.writeInt( uint( rate * channels * ( bits >> 3 ) ) );
        _bytes.writeShort( uint( channels * ( bits >> 3 ) ) );
        _bytes.writeShort( bits );
        _bytes.writeUTFBytes( WaveEncoder.DATA );
        _bytes.writeInt( data.length );
        _bytes.writeBytes( data );
        _bytes.position = 0;

        return _bytes;
    }

ByteArray to Base64 encoding

public static function encode(data:ByteArray):String
    {
        var out:ByteArray = new ByteArray();
        //Presetting the length keep the memory smaller and optimize speed since there is no "grow" needed
        out.length = (2 + data.length - ((data.length + 2) % 3)) * 4 / 3; //Preset length //1.6 to 1.5 ms
        var i:int = 0;
        var r:int = data.length % 3;
        var len:int = data.length - r;
        var c:uint; //read (3) character AND write (4) characters
        var outPos:int = 0;
        while (i < len)
        {
            //Read 3 Characters (8bit * 3 = 24 bits)
            c = data[int(i++)] << 16 | data[int(i++)] << 8 | data[int(i++)];

            out[int(outPos++)] = _encodeChars[int(c >>> 18)];
            out[int(outPos++)] = _encodeChars[int(c >>> 12 & 0x3f)];
            out[int(outPos++)] = _encodeChars[int(c >>> 6 & 0x3f)];
            out[int(outPos++)] = _encodeChars[int(c & 0x3f)];
        }

        if (r == 1) //Need two "=" padding
        {
            //Read one char, write two chars, write padding
            c = data[int(i)];

            out[int(outPos++)] = _encodeChars[int(c >>> 2)];
            out[int(outPos++)] = _encodeChars[int((c & 0x03) << 4)];
            out[int(outPos++)] = 61;
            out[int(outPos++)] = 61;
        }
        else if (r == 2) //Need one "=" padding
        {
            c = data[int(i++)] << 8 | data[int(i)];

            out[int(outPos++)] = _encodeChars[int(c >>> 10)];
            out[int(outPos++)] = _encodeChars[int(c >>> 4 & 0x3f)];
            out[int(outPos++)] = _encodeChars[int((c & 0x0f) << 2)];
            out[int(outPos++)] = 61;
        }

        return out.readUTFBytes(out.length);
    }

    public static function decode(str:String):ByteArray
    {
        var c1:int;
        var c2:int;
        var c3:int;
        var c4:int;
        var i:int = 0;
        var len:int = str.length;

        var byteString:ByteArray = new ByteArray();
        byteString.writeUTFBytes(str);
        var outPos:int = 0;
        while (i < len)
        {
            //c1
            c1 = _decodeChars[int(byteString[i++])];
            if (c1 == -1)
                break;

            //c2
            c2 = _decodeChars[int(byteString[i++])];
            if (c2 == -1)
                break;

            byteString[int(outPos++)] = (c1 << 2) | ((c2 & 0x30) >> 4);

            //c3
            c3 = byteString[int(i++)];
            if (c3 == 61)
            {
                byteString.length = outPos
                return byteString;
            }

            c3 = _decodeChars[int(c3)];
            if (c3 == -1)
                break;

            byteString[int(outPos++)] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);

            //c4
            c4 = byteString[int(i++)];
            if (c4 == 61)
            {
                byteString.length = outPos
                return byteString;
            }

            c4 = _decodeChars[int(c4)];
            if (c4 == -1)
                break;

            byteString[int(outPos++)] = ((c3 & 0x03) << 6) | c4;
        }
        byteString.length = outPos
        return byteString;
    }

    public static function InitEncoreChar():Vector.<int>
    {
        var encodeChars:Vector.<int> = new Vector.<int>(64, true);

        // We could push the number directly
        // but I think it's nice to see the characters (with no overhead on encode/decode)
        var chars:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        for (var i:int = 0; i < 64; i++)
        {
            encodeChars[i] = chars.charCodeAt(i);
        }

        return encodeChars;
    }

I send that base64 data to my service request php side i got the '$this->request->voiceSample' parameter and decode base64 to .wav file

 file_put_contents('name.wav', base64_decode($this->request->voiceSample));

After load that "name.wav" file in Riffpad I got issue

The file seems to be corrupt for a RIFF.

Any one please give me the advice to solve this issue...

Aucun commentaire:

Enregistrer un commentaire