Reading bytes in particular order
Blitz3D Forums/Blitz3D Beginners Area/Reading bytes in particular order
| ||
Sorry for the crappy thread title. The problem I have here ,isn't so much how to do something, but how to do it in a sensible, efficient way. The principle idea of the code, is to do with mp3 sound data. In the file, the sound data can be either mono or stereo. In the case of mono sounds, the data is as you'd expect, in consecutive bytes, yet in the case of stereo sound, the bytes alternate between left then right. This isn't so much of a big deal in itself, but with the data, I wish to draw a kinda waveform image. This reuquires (thanks to the Line command ) needing to track the last and current, or current and next points of data so the line can be drawn between the two. That's where my problems start. I have tried to read bytes in chunks of 4 at a time, this way, I can capture two bytes worth of data even for a stereo sound (two for each channel). If it's a mono sound, then of course, 4 bytes are captured in this way, so the line drawing is just repeated to draw the additional bytes. Here's what I have so far, the actual drawing routine and other aspects aren't so relevant to the issue, so don't worry if there's functions which aren't available here, the crux of the matter is really just in the For/Next and reading of the data which is all presented below: Local nChannelBytes=(nChannels Shl True) Local nChannelStep=nChannelBytes-1 Dim Bytes(nChannelBytes) Local nLastLByte=-1 Local nLastLX=0 Local nLastRByte=-1 Local nLastRX=0 For nIterByte=0 To (WaveFormResolutionWidth-nChannelStep) For nIterReadBytes=0 To (nChannelStep) Bytes(nIterReadBytes)=PeekByte(bBank,nIterByte+nIterReadBytes) If (nChannels=1) If (nLastLByte<1)Then nLastLByte=Bytes(0) DrawLine(LeftChannelColour,nLastLX,nIterByte,nLastLByte,Bytes(nIterReadBytes)) nLastLX=nIterByte+nIterReadBytes nLastLByte=Bytes(nIterReadBytes) Else If (nChannels=2) DrawLine(LeftChannelColour,nLastLX,nIterByte,nLastLByte,Bytes(nIterReadBytes)) nLastLX=nIterByte+nIterReadBytes nLastLByte=Bytes(nIterReadBytes) If (nIterReadBytes) If (nLastLByte<1)Then nLastLByte=Bytes(0) DrawLine(RightChannelColour,nLastRX,nIterByte+1,nLastRByte,Bytes(nIterReadBytes+1)) nLastRX=nIterByte+nIterReadBytes+1 nLastRByte=Bytes(nIterReadBytes+1) End If End If End If nIterReadBytes=nIterReadBytes+nChannels Next nIterByte=nIterByte+nChannelBytes Next If anyone has any advice on how to smarten/speed this up, I'd be realyl grateful. Thanks :) |
| ||
hi one aproach should be to get the first sample and then repeat from the second to the last drawing from prvious to current: Previous = GetNextSample() for Count=SecondSample to LastSample Current = GetNextSample drawline fromPrevious to Current Previous = Current next Juan |
| ||
The difficult part, is reading the "Previous" and "Next" data in the correct order, since the order changes depending on the channels: i.e. MONO: byte1= Left Channel byte1 byte2= Left Channel byte2 byte3= Left Channel byte3 byte4= Left Channel byte4 STEREO: byte1= Left Channel byte1 byte2= Right Channel byte1 byte3= Left Channel byte2 byte4= Right Channel byte2 Sorry if i wast being so clear :) Of course I could write out separate routines depending on the channels, but I would prefer to be able to 'automatically' sort the bytes if you know what I mean? |
| ||
only one byte per sample? normally the samples 8/16 bits and mono/stereo any way, i think that is more easy to read if you construct a NextSample function that evaluates mono/stereo and the like and a higher routine that doesn't care about that. isn't it? be aware of 16 bit samples, they normally are stored lo/hi litle endiand style, so the actual 16 bit value must constructed by: First + Second shl 8, being the first the one in lower memory addres and the Second the next in the up adjacent memory address. is it necesary to draw a line?, why not simply plot the dots, or draw a vertical line from 0 to SampleValue, in this way you still has a good graph of the wave. Juan |
| ||
You could also create a 2-dimentional array. Dim ArraySamples(10000, 2) Read the left channel into ArraySamples(xxx, 1) and the right channel into ArraySamples(xxx, 2). The xxx is the counter you use to increment the arrayindex after you've read both left and right bytes. If you want to draw the left channel, you only use ArraySamples(xxx, 1), looping throuhg the entire array and you're done. So: byte1 => ArraySamples(1, 1) byte2 => ArraySamples(1, 2) byte3 => ArraySamples(2, 1) byte4 => ArraySamples(2, 2) byte5 => ArraySamples(3, 1) byte6 => ArraySamples(3, 2) byte7 => ArraySamples(4, 1) byte8 => ArraySamples(4, 2) byte9 => ArraySamples(5, 1) byte10 => ArraySamples(5, 2) ... Use the first index as the byte-counter, use the second index as the channel (1 = left, 2 = right). |
| ||
be aware of 16 bit samples, they normally are stored lo/hi litle endiand style, so the actual 16 bit value must constructed by: First + Second shl 8, being the first the one in lower memory addres and the Second the next in the up adjacent memory address. is it necesary to draw a line?, why not simply plot the dots, or draw a vertical line from 0 to SampleValue, in this way you still has a good graph of the wave. Thanks, Charrua yes the number of bits is important. I'd not considered tht yet (oops!) although the basic format is the same, since the bytes themselves are still ordered left than right in stereo, (then of course, there's spdif 24-bit sounds.... ) so a 16-bit sample would just mean: MONO byte 1 - left channel bigendian1 byte 2 - left channel littleendian1 byte 3 - left channel bigendian2 byte 4 - left channel littleendian2 byte 5 - left channel bigendian3 byte 6 - left channel littleendian3 byte 7 - left channel bigendian4 byte 8 - left channel littleendian4 STEREO byte 1 - left channel bigendian1 byte 2 - left channel littleendian1 byte 3 - right channel bigendian1 byte 4 - right channel littleendian1 byte 5 - left channel bigendian2 byte 6 - left channel littleendian2 byte 7 - right channel bigendian2 byte 8 - right channel littleendian2 ________________________________________________ PowerPC - thanks, that's a really smart way of dealing with it :) |