I am weighing the benefits of using [b:2pqqqad7]lock / unlock[/b:2pqqqad7] in real time vs. [b:2pqqqad7]readData[/b:2pqqqad7] offline. If I could actually get lock / unlock to work, it would help a lot.
By in real time, I would like to get the data of the wave form being played at it’s current position + a few seconds of data of the wave form before it’s current position. I can’t have a buffer of the data because at times, the audio may play backwards. This is also why I don’t think I can use [b:2pqqqad7]channel->getWaveData[/b:2pqqqad7] because that only provides data from the current position onwards, and not prior.
Here is a block of code I’ve used.
unsigned int offset;
result = channel->getPosition(&offset, FMOD_TIMEUNIT_PCMBYTES);
unsigned int length=1000; // Just for testing right now void *ptr1; void *ptr2; unsigned int len1; unsigned int len2; result = sound->lock(offset, length, &ptr1, &ptr2, &len1, &len2); [ERRCHECK:result]; NSLog(@"offset:%d len1: %d", offset, len1); result = sound->unlock(&ptr1, &ptr2, len1, len2); [ERRCHECK:result];
The problem with this is that the getPosition returns PCM Bytes and my sound is compressed in memory ([b:2pqqqad7]createSound[/b:2pqqqad7] with MP2 / MP3 file COMPRESSED_SAMPLE). Eventually I get an error:
list:2pqqqad7 An invalid parameter was passed to this function.[/list:u:2pqqqad7]
Where my offset becomes larger than the file’s actual length compressed.
So I tried using [b:2pqqqad7]getPosition[/b:2pqqqad7] RAWBYTES instead, but then I get the following error after [b:2pqqqad7]getPosition[/b:2pqqqad7]:
list:2pqqqad7 Unsupported file or audio format. [/list:u:2pqqqad7]
unsigned int offset;
result = channel->getPosition(&offset, FMOD_TIMEUNIT_RAWBYTES);
Any help would be greatly appreciated!
- CuriousG asked 9 years ago
readData worked very well for an older project of mine where I read wav/mp3 files and did some audio processing on it.
I would e.g. typedef short PCM_sample; so you have a 16 bit type and can create an array of samples, instead of bytes. For 8 bit you’d have to change your typedef. Just pass that array to readData with some (char*) cast.
Why do you want to use float if your input data is 16 bit integer? Processing an array of float is slower. I think you’d have to loop over every sample of your PCM_sample array. float f = (float) myArray[i]; (that is done implicitly without the cast)
PS: I didn’t make my mind up about little / big endian of PCM and different compilers. If that’s wrong on your OS you’ll quickly see 😉
PS2: With PCM_sample you still have to be careful about stereo data. Left / right channel samples are in alternating order.
- thespiders answered 9 years ago
Well after trying many different things, I’ve come to the following conclusions:
[list:1jevk97r]1) lock / unlock will give compressed data on a CREATE_COMPRESSEDSAMPLE. I don’t think I can use that.
2) seekData doesn’t work on a createSound.
3) getWaveData provides too little data (only 16384 samples, with is about 1/3 of a second of information) and is unable to provide data that is before the current play position.
So I am currently looking at using readData on a createStream. The purpose of all this is to create a peak file for visualization. My question is now, how do I convert the void * to an array of samples represented in floats?
const unsigned int CHUNKSIZE = 4096;
void *data = NULL;
unsigned int read = 0;
data = malloc(CHUNKSIZE);
result = soundForPeaks->readData((char *)data, CHUNKSIZE, &read);
for (int i=0; i<read ; i++)
fprintf("Float of data at pos: %0.2f\n", (float *)data[i];
Yep, probably a very basic C question I know. Objective C has rotted my brain. Haha.
But I also have the sneaking suspision that readData might give me just raw byte data and not sample data, meaning I may come across a situation where the read position cuts through half of a sample. Is that correct?
Thanks for the continued help.
- CuriousG answered 9 years ago
Please login first to submit.