I have been trying to visualize an audio track with fmod ex’s C# api.
So far I have been successful by just loading the whole sound and retrieving the raw wave data with the @lock() function. The problem with this method is that the whole audio file needs to be loaded and encoded and saved in memory, which can take a lot of space for bigger files.
I thought to overcome this problem I would simply create a stream and use readData() to get my wave data in chunks.
This works ok, although I noticed I could retrieve 4 times less data (bytes) when using readData(). Also the data retrieved with @lock() differs from readData(). So I guessed (no source code so guessing is all I can do here :() the data is red 4 bytes at once. I implemented that idea by the use of ints instead of bytes. Now I at least have the same amount of output, but I have not yet been able to match to lock() with the readData() data.
Test data, I used the default windows ‘chimes.wav’ as test subject (WAV, PCM16, stereo, 16-bit).
The first 8 byte output of lock(): 2, 0, 3, 0, 9, 0, 6, 0
The first 2 32-bit int output of readData(): 53347244, 75302086
The first 8 byte output of readData(): 172, 3, 46, 3, 198, 4, 125, 4
These two results are not corresponding on bit level so I am in the dark here as to how to interpret the data retrieved from readData().
Can somebody explain what I am missing here?
FMOD.Sound streamSound = null;
FMOD.Sound loadedSound = null;
result = system.createStream(filename, FMOD.MODE.SOFTWARE | FMOD.MODE._2D, ref streamSound);
result = system.createSound(filename, FMOD.MODE.SOFTWARE | FMOD.MODE._2D, ref loadedSound);
// get the length of the data
uint soundLengthPCMBytes = 0;
uint soundLengthPCM = 0;
sound.getLength(ref soundLengthPCMBytes, FMOD.TIMEUNIT.PCMBYTES);
sound.getLength(ref soundLengthPCM, FMOD.TIMEUNIT.PCM);
// lock method
IntPtr lockPtr1 = Marshal.AllocHGlobal((int)soundLengthPCMBytes);
IntPtr lockPtr2 = IntPtr.Zero;
uint len1 = 0;
uint len2 = 0;
byte lockBuffer = new byte[soundLengthPCMBytes];
result = loadedSound.@lock(0, soundLengthPCMBytes, ref lockPtr1, ref lockPtr2, ref len1, ref len2);
Marshal.Copy(lockPtr1, lockBuffer, 0, (int)soundLengthPCMBytes);
result = loadedSound.unlock(lockPtr1, lockPtr2, len1, len2);
// read method
uint chunk = 1024;
uint read = 0;
uint progress = 0;
IntPtr readPtr1 = Marshal.AllocHGlobal((int)chunk);
//byte readBuffer = new byte[soundLengthPCM];
int readBuffer = new int[soundLengthPCM];
while(progress < soundLengthPCM – 1)
if (soundLengthPCM – progress < chunk)
chunk = soundLengthPCM – progress – 1;
result = streamSound.readData(readPtr1, chunk, ref read); ERRCHECK(result); Marshal.Copy(readPtr1, readBuffer, (int)progress, (int)read); progress += read;
- Mino asked 10 years ago
creating a stream prebuffers a chunk of data, and internally calls readData.
This means the read cursor is somewhere into the file, rather than at the start. The solution is to use openoly to stop the first read, or just use a call to seekData(0)
Please login first to submit.