raw sound byteArray to float Array - arrays

I'm trying to convert the byteArray of a Sound Object to an array with floats. The Sound Object plays back fine & at full length, but the float Array i get from it is cut off (but sounds correct), so i must be doing something wrong in the conversion:
var s:Sound = mySound;
s.play(); // plays fine
var bytes:ByteArray = new ByteArray();
bytes.endian = Endian.LITTLE_ENDIAN;
s.extract(bytes, s.bytesTotal, 0);
var leftChannel:Array = new Array();
var rightChannel:Array = new Array();
bytes.position = 0;
while (bytes.bytesAvailable)
{
leftChannel.push(bytes.readFloat());
rightChannel.push(bytes.readFloat());
}
and this is what i get:
The top two channels are the original Sound Object.
The lower two is the float Array Data. I aligned them so you can see that the beginning is cut off and obviously the length is incorrect.
Thanks for any answers...

ok there were two problems:
the mp3 file i was importing was somehow corrupt, that caused the beginning to be cut off
the length i defined to extract was not correct, to find the full sound length use
var numTotalSamples:Number = int(s.length * 44.1); //assuming 44.1kHz sample rate
then:
s.extract(bytes, numTotalSamples, 0);

Related

Flash multidimensional array of movieclips

Programming an educational program with fractions, you can touch a part of a fraction on a digiboard (or pc screen) that becomes colored/active. Touch or click it a second time and it becomes white/unactive again. And so on...
To reset a fraction with all of its colored parts to white I want to press a single button once that's calling the function resetFraction. Please take a look at the code below, it seems to go wrong at the two-dimensional array with movieclips - no change from colored to a white part. All arrays containing names of movieclips:
//array with fractions containing the (real) movieclips of parts
//mc_frac1 has one part, mc_frac2 has two parts, and so on
var fractionAr : Array = new Array(mc_frac1, mc_frac2, mc_frac3, mc_frac4, mc_frac5);
//array with max-index for partAr, see below
var maxPart : Array = new Array(1,2,3,4,5);
//array with parts, 2 dimensional with a variable index per fraction
var partAr : Array = new Array(
new Array(mc_part1_1),
new Array(mc_part2_1, mc_part2_2),
new Array(mc_part3_1, mc_part3_2, mc_part3_3),
new Array(mc_part4_1, mc_part4_2, mc_part4_3, mc_part4_4),
new Array(mc_part5_1, mc_part5_2, mc_part5_3, mc_part5_4, mc_part5_5));
//put all parts back to 'untouched' (color white)
function resetFraction(var FracNum : Number) {
var p : Number = FracNum;
for (var i = 0; i < maxPart[p]; i++) {
fractionAr[p-1].partAr[p-1][i].gotoAndStop(1);
}
}
This code below is split up in portions to see where it goes wrong:
p = 4;
mc_frac4.mc_part4_2.gotoAndStop(1); //works
fracAr[p-1].mc_part4_2.gotoAndStop(1); //works
//but
fracAr[p-1].partAr[3][1].gotoAndStop(1); //does nothing
The two-dimensional array seems to be the problem.
Anyone can help me? It saves a lot of code to realise this with one function.
Thanks a lot.
I'm out!
Instead of the dot (.) I use the array acces operators ([ ]) and quotes (" ") in the partAr array:
var partAr : Array =
new Array(
new Array("mc_part1_1"),
new Array("mc_part2_1", "mc_part2_2"), and so on...
while the fourth line in the function becomes this:
function resetFraction(var FracNum : Number) {
var p : Number = FracNum;
for (var i = 0; i < maxPart[p]; i++) {
fractionAr[p-1][partAr[p-1][i]].gotoAndStop(1);
}
}
Simple, isn't it?

Doing something at a certain point in an array Flash AS3

I am making a Rhythm game and I am looking to change the time when the song reaches a certain point; but I do not know how to do this.
This is my array controlling what note is being played (1=Z,2=X,3=N,4=M):
var lvlArray1:Array = new Array(0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,
3,0,0,0,3,0,0,0,3,0,0,3,0,0,0,0,0,
0,0,0,0,0,1,4,1,4,0,0,0,0,0,0,0,0);
And to control my tempo I have:
//sTempo is how many frames it takes before
//a note is created. Because it's 12, and
//the frame rate is 24, it will take a half of a second
//for a note to be made
var sTempo:Number = 12;
How would I go about changing the tempo to say 6 when the 40th note is played (where the 1,4,1,4 starts)
I feel like this might be something incredibly simple, but my mind is just blank.
Thank you for your time!
Without having much code to go on, this is what I've cooked up.
You can have a separate Dictionary of tempo changes that correspond to the index of the lvlArray1. And you can check that dictionary whenever you're about to create a new note.
Example:
var tempoChanges:Dictionary = new Dictionary();
tempoChanges[39] = 6; // specify a tempo change to 6 for the 40th note (index 39)
// check to see if there's a tempo change for index i
if(tempoChanges[i] != undefined)
{
// if there is, change the tempo to that value
sTempo = tempoChanges[i];
}

What is a compact way to save a float32array to disk on node.js?

JSON.stringify is obviously not space-efficient. What is the most elegant way to serialize and store a float32array using Node.js?
EDIT: People are closing the question for reasons such as being "opinion based" and "lack of an understanding of the problem". I seriously believe the first one was a missclick. For the second one, maybe this makes it more clear:
var fs = require("fs");
var len = 1000*1000*10;
var big_array = new Float32Array(len);
for (var i=0; i<len; ++i)
big_array[i] = Math.random();
// OBVIOUSLY NOT SPACE EFFICIENT \/
fs.writeFileSync("big_array.json",JSON.stringify(big_array));
It is not space efficient because you are representing numbers as strings, so an 8 bytes float will be using as much as ~20 utf8 chars, which is a waste. The question is: how to store the array in a space-efficient manner?
Finally I managed to write float32array to disk with nodejs and retrieve them on the browser, and I hope it will help you.
Write Float32Array to binary file in NodeJS
var fs = require('fs');
var wstream = fs.createWriteStream('data.dat');
var data = new Float32Array([1.1,2.2,3.3,4.4,5.5]);
//prepare the length of the buffer to 4 bytes per float
var buffer = new Buffer(data.length*4);
for(var i = 0; i < data.length; i++){
//write the float in Little-Endian and move the offset
buffer.writeFloatLE(data[i], i*4);
}
wstream.write(buffer);
wstream.end();
Read the file and convert it to a Float32Array on a Browser
var urlToFloatFile = 'data.dat';
var request = new XMLHttpRequest();
request.open('GET', urlToFloatFile, true);
//specify the response type as arraybuffer
request.responseType = 'arraybuffer';
request.onload = function (msg) {
var yourFloatData = new Float32Array(this.response);
console.log(yourFloatData);
};
request.send();
Thanks to #ben_a_adams from WebGL Dev List GGroup https://groups.google.com/forum/#!topic/webgl-dev-list/EbGUi_iSEx8 for the client side code
I've create a simple test to test roughly how much space a JSON serialization of a float array differs from a binary representation and the results are:
2.000.000 floating point values
7.8MB on a binary file
38.5MB on a JSON file
17.5 on a Gzipped JSON file
There is actually a much simpler version possible
let fs = require('fs')
let data = [150, 180]
fs.writeFileSync('mydata', new Buffer(new Uint32Array(data).buffer))
fs.readFile('mydata', (err, buf) => {
let restoredData = new Uint32Array(buf.buffer, buf.offset, buf.byteLength/4)
console.log(data[1])
console.log(restoredData[1])
});
Easy, clean way to do it:
const float32Array = new Float32Array([.69,.420])
const buffer = Buffer.from(float32Array.buffer)
fs.writeFileSync(filePath, buffer)
const loadedBuffer = fs.readFileSync(filePath)
const newFloat32Array = new Float32Array(loadedBuffer.buffer)
I believe you could use Meteor's EJSON:
http://docs.meteor.com/#ejson
https://npmjs.org/package/meteor-ejson
EJSON is an extension of JSON to support more types. It supports all
JSON-safe types, as well as:
Date (JavaScript Date)
Binary (JavaScript Uint8Array or the result of EJSON.newBinary)
User-defined types (see EJSON.addType. For example, Meteor.Collection.ObjectID is implemented this way.)

Image Analysis Program Based on Hashcode Method Resulting in Errors

I am trying to write a program that will recognize an image on the screen, compare it against a resource library, and then calculate based on the result of the image source.
The first thing that I did was to create the capture screen function which looks like this:
private Bitmap Screenshot()
{
System.Drawing.Bitmap Table = new System.Drawing.Bitmap(88, 40, PixelFormat.Format32bppArgb);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(RouletteTable);
g.CopyFromScreen(1047, 44, 0, 0, Screen.PrimaryScreen.Bounds.Size);
return Table;
}
Then, I analyze this picture. The first method I used was to create two for loops and analyze both the bitmaps pixel by pixel. The problem with this method was time, it took a long time to complete 37 times. I looked around and found the convert to bytes and the convert to hash methods. This is the result:
public enum CompareResult
{
ciCompareOk,
ciPixelMismatch,
ciSizeMismatch
};
public CompareResult Compare(Bitmap bmp1, Bitmap bmp2)
{
CompareResult cr = CompareResult.ciCompareOk;
//Test to see if we have the same size of image
if (bmp1.Size != bmp2.Size)
{
cr = CompareResult.ciSizeMismatch;
}
else
{
//Convert each image to a byte array
System.Drawing.ImageConverter ic = new System.Drawing.ImageConverter();
byte[] btImage1 = new byte[1];
btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
byte[] btImage2 = new byte[1];
btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());
//Compute a hash for each image
SHA256Managed shaM = new SHA256Managed();
byte[] hash1 = shaM.ComputeHash(btImage1);
byte[] hash2 = shaM.ComputeHash(btImage2);
for (int i = 0; i < hash1.Length && i < hash2.Length&& cr == CompareResult.ciCompareOk; i++)
{
if (hash1[i] != hash2[i])
cr = CompareResult.ciPixelMismatch;
}
}
return cr;
}
After I analyze the two bitmaps in this function, I call it in my main form with the following:
Bitmap Table = Screenshot();
CompareResult success0 = Compare(Properties.Resources.Result0, Table);
if (success0 == CompareResult.ciCompareOk)
{ double result = 0; Num.Text = result.ToString(); goto end; }
The problem I am getting is that once this has all been accomplished, I am always getting a cr value of ciPixelMismatch. I cannot get the images to match, even though the images are identical.
To give you a bit more background on the two bitmaps, they are approximately 88 by 40 pixels, and located at 1047, 44 on the screen. I wrote a part of the program to automatically take a picture of that area so I did not have to worry about the wrong location or size being captured:
Table.Save("table.bmp");
After I took the picture and saved it, I moved it from the bin folder in the project directly to the resource folder and ran the program again. Despite all of this, the result is still ciPixelMismatch. I believe the problem lies within the format that the pictures are being saved as. I believe that despite them being the same image, they are being analyzed in different formats, maybe one of the pictures contains a bit more information than the other which is causing the mismatch. Can somebody please help me solve this problem? I am just beginning with my c# programming, I am 5 days into the learning process, and I am really at a loss for this.
Yours sincerely,
Samuel

put live audio input data into array

Hey I am using GetUserMedia() to capture audio input from user's microphone. Meanwhile I want to put captured values into an array so I can manipulate with them. I am using the following code but the problem is that my array gets filled with value 128 all the time (I print the results in console for now), and I can't find my mistake. Can someone help me find my mistake?
//create a new context for audio input
context = new webkitAudioContext();
var analyser = null;
var dataarray = [];
getLiveInput = function() {
navigator.webkitGetUserMedia({audio: true},onStream,onStreamError);
};
function onStream(stream)
{
var input = context.createMediaStreamSource(stream);
analyser = context.createAnalyser();
var str = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(str);
for (var i = 0; i < str.length; i++) {
var value = str[i];
dataarray.push(value);
console.log(dataarray)
}//end for loop
}//end function
function onStreamError(e) {
console.error('Streaming failed: ', e);
};
The values returned from getByteTimeDomainData are 8 bit integers, from 0 to 255. 128, which is half way, basically means "no signal". It is the equivalent of 0 in PCM audio data from -1 to 1.
But ANYWAY - there are a couple problems:
First, you're never connecting the input to the analyser. You need input.connect(analyser) before you call analyser.getByteTimeDomainData().
The second problem isn't with your code so much as it's just an implementation issue.
Basically, the gotStream function only gets called once - and getByteTimeDomainData only returns data for 1024 samples worth of audio (a tiny fraction of a second). The problem is, this all happens so quickly and for such a short period of time after the stream gets created, that there's no real input yet. Try wrapping the analyser.getByteTimeDomainData() call and the loop that follows it in a 1000ms setTimeout and then whistle into your microphone as soon as you give the browser permission to record. You should see some values other than 128.
Here's an example: http://jsbin.com/avasav/5/edit

Resources