Android Drum machine
-
- KVRist
- Topic Starter
- 154 posts since 15 Feb, 2012
https://www.dropbox.com/s/tue93finb42k9ib/sinc5.wav
Its a sine at c5, its playing c4 in my test app.
EDIT: Just to be sure, I call getSampleRate on my AudioTrack once it is initialized, and it return 44100.
EDIT: I just realized I had the sample as a stereo file which explains why in mono it is playing at half the frequency. SO that problem is solved. But there still remains the tempo problem.
Now that the sample problem is sorted out it confirms that the sample is being read and played correctly. The sample is a sine at c5, and audio track is playing back a sine c5 with no pitch or timbre change, or distortion whatsoever.
Its a sine at c5, its playing c4 in my test app.
EDIT: Just to be sure, I call getSampleRate on my AudioTrack once it is initialized, and it return 44100.
EDIT: I just realized I had the sample as a stereo file which explains why in mono it is playing at half the frequency. SO that problem is solved. But there still remains the tempo problem.
Now that the sample problem is sorted out it confirms that the sample is being read and played correctly. The sample is a sine at c5, and audio track is playing back a sine c5 with no pitch or timbre change, or distortion whatsoever.
-
- KVRist
- 152 posts since 14 Jun, 2011
Bingo! That's what I suspected, therefore I wanted the file.Ap0C552 wrote: EDIT: I just realized I had the sample as a stereo file which explains why in mono it is playing at half the frequency. SO that problem is solved. But there still remains the tempo problem.
Now that the sample problem is sorted out it confirms that the sample is being read and played correctly. The sample is a sine at c5, and audio track is playing back a sine c5 with no pitch or timbre change, or distortion whatsoever.
Great that you sorted it out
When you read a 2-channel (stereo), 16bit wav, the byte stream is as followed:
Code: Select all
00000000 11111111 00000000 11111111
<------> <------> <------> <------>
lowCh1 higCh1 lowCh2 higCh2
This resource explains very well how multi channel files are organized. It also points to the bastardized wave formats and header types.
http://home.roadrunner.com/~jgglatt/tech/wave.htm
I would say, since you're handling your sample as bytes (that's what you do, right?), and you count every byte in your sequencer to calculate the time, then you count 4 bytes for each sample, which finally results in a 4 times faster sequencer speed.SO that problem is solved. But there still remains the tempo problem.
Count the frames instead, and the tempo will be fine.
-
- KVRist
- Topic Starter
- 154 posts since 15 Feb, 2012
Yes that is the tempo problem!!! How did this elude me! :s
I am doing my calculation as
long bufferTime=(1000000000/44100)*buffSize;
where buffSize is the size in bytes, when it should be buffSize/2 aka the size in short.
Finally I can get back to experimenting with the sequencer!!
I am just wondering though. How do you write new triggers to play into the sequencer when it is playing at realtime. Since with this approach you are writting lots of data ahead of time to the audiotrack.
I am doing my calculation as
long bufferTime=(1000000000/44100)*buffSize;
where buffSize is the size in bytes, when it should be buffSize/2 aka the size in short.
Finally I can get back to experimenting with the sequencer!!
I am just wondering though. How do you write new triggers to play into the sequencer when it is playing at realtime. Since with this approach you are writting lots of data ahead of time to the audiotrack.
-
- KVRist
- 152 posts since 14 Jun, 2011
Actually it's bufferSize/4, keep in mind that you're playing a stereo file, which means 2 bytes for each channel.Ap0C552 wrote: where buffSize is the size in bytes, when it should be buffSize/2 aka the size in short.
Just keep in mind, that always the audio process (an independent thread) is the master of almost everything. The audio loop has to ask the sequencer if there's something to play, never the opposite way.Ap0C552 wrote:Finally I can get back to experimenting with the sequencer!!
I am just wondering though. How do you write new triggers to play into the sequencer when it is playing at realtime. Since with this approach you are writting lots of data ahead of time to the audiotrack.
The sequencer is just the orchestrator, the keeper of the plan whatever has to be played at a specific time. That plan can be changed all the time, by someone tapping the screen, by a sequence loader, by a song arranger, whatever. It can be changed by any thread in the system (the gui thread, some loader threads, also by the audio thread).
So good luck then;)
-
- KVRist
- Topic Starter
- 154 posts since 15 Feb, 2012
I understand that.
But...
My audio loop is writing as fast as it can to the AudioTrack. And loading its buffer with lots data.
Now if I change something in the sequencer, the audiotrack buffer has already been loaded with lots of data to play. So the loop that writes to the audio track can start writing something different according to sequencer changes, but the audiotrack might have a a large buffer full of data to play before that change is realized.
But...
My audio loop is writing as fast as it can to the AudioTrack. And loading its buffer with lots data.
Now if I change something in the sequencer, the audiotrack buffer has already been loaded with lots of data to play. So the loop that writes to the audio track can start writing something different according to sequencer changes, but the audiotrack might have a a large buffer full of data to play before that change is realized.
-
- KVRist
- 152 posts since 14 Jun, 2011
You have to mix all playing sample buffers together (from every playing sample) to a single buffer before you write it to the audioTrack. E.g. when you have 6 samplers, loop over your samplers, for each get its buffer and push it to some mixer. When you're through take the final mixdown and write it to the audioTrack. To be able to do this you need to have short[] or float[] buffers instead of byte buffers, only the final mixdown has to be converted back into bytes before the write.
-
- KVRist
- Topic Starter
- 154 posts since 15 Feb, 2012
That was not really what I was getting at.
Forget about multiple samples for this example.
What I am worried about is changes is sequencer data being recognized in the playback in realtime.
My loop for generating the output buffer is writing to the audiotrack at no set maximum speed. Correct? It is writing as fast as it can to audio track. Now in a period of some time, lets say 1 second, it could have wrote 15 seconds of audio to the audiotrack. So there is 15 seconds of audio buffered in audio track.
Now if I make a change to sequencer data, that change will immediately be recognized in my output loop that is writing to audiotrack. But that change in sequencer data will not be recognized in the audio being play for a long time, since my output loop has filled the audiotrack buffer up with a lot of audio waiting to be played correct?
So by writing internal buffer with no limit to speed, its like I build up a gigantic input latency in my sequencer.
Forget about multiple samples for this example.
What I am worried about is changes is sequencer data being recognized in the playback in realtime.
My loop for generating the output buffer is writing to the audiotrack at no set maximum speed. Correct? It is writing as fast as it can to audio track. Now in a period of some time, lets say 1 second, it could have wrote 15 seconds of audio to the audiotrack. So there is 15 seconds of audio buffered in audio track.
Now if I make a change to sequencer data, that change will immediately be recognized in my output loop that is writing to audiotrack. But that change in sequencer data will not be recognized in the audio being play for a long time, since my output loop has filled the audiotrack buffer up with a lot of audio waiting to be played correct?
So by writing internal buffer with no limit to speed, its like I build up a gigantic input latency in my sequencer.
-
- KVRist
- 152 posts since 14 Jun, 2011
No, AudioTrack just buffers its own bufferSize, and if your audioSystem is faster than that, the AudioTrack just lets your process wait. So don't worry about that, if your audioProcess asks the sequencer for "events" (something to do), then it'll be executed within the latency time (the audioTrack's buffer size).Ap0C552 wrote:But that change in sequencer data will not be recognized in the audio being play for a long time, since my output loop has filled the audiotrack buffer up with a lot of audio waiting to be played correct?
Usually it's more the other way... that your audio process is not fast enough to serve the audioTrack with enough data
-
- KVRist
- Topic Starter
- 154 posts since 15 Feb, 2012
Ok I see. When I tested this I had some bugs, but now my test are working for realtime sequencer changes.
I think a sequencer with crisp timing will be a reality for me now!
My first born will be named Planeth
I think a sequencer with crisp timing will be a reality for me now!
My first born will be named Planeth
-
- KVRist
- 152 posts since 14 Jun, 2011
Great, so good luck with it. Looking forward to see the finished app.Ap0C552 wrote:Ok I see. When I tested this I had some bugs, but now my test are working for realtime sequencer changes.
I think a sequencer with crisp timing will be a reality for me now!
yeahAp0C552 wrote:My first born will be named Planeth
-
- KVRist
- Topic Starter
- 154 posts since 15 Feb, 2012
Just wondering. You were talking about converting and convert back. AudioTrack has write short method. Can I not just keep in short then?
-
- KVRist
- 152 posts since 14 Jun, 2011
Cannot answer that for sure, but it may be. Unfortunately this is not clearly described in the api docs. I would just try. If it is actually what it looks like, a write method for 16bit short samples, it could have a better performance as the byte method, because the short samples will be splitted into bytes at the native layer.Ap0C552 wrote:Just wondering. You were talking about converting and convert back. AudioTrack has write short method. Can I not just keep in short then?
Internally, the audiotrack does that:
Code: Select all
native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat);-
- KVRist
- Topic Starter
- 154 posts since 15 Feb, 2012
-
- KVRist
- 367 posts since 20 Aug, 2004 from Sydney, Australia
Why are you guys (android) torturing yourselves..?!
Buy an iPad and be happy if you want to create music that is...
Android OS is not optimIsed for music production I'm afraid
Buy an iPad and be happy if you want to create music that is...
Android OS is not optimIsed for music production I'm afraid