В настоящее время я пишу код для примера секвенсора в Android. Я использую класс AudioTrack. Мне сказали, что единственный правильный способ получить точное время - это использовать время AudioTrack. Например, я знаю, что если я запишу буфер X сэмплов в AudioTrack, воспроизводимый со скоростью 44100 сэмплов в секунду, то время записи будет (1/44100)X секунд.
Затем вы используете эту информацию, чтобы узнать, какие сэмплы и когда должны быть записаны.
Я пытаюсь реализовать свою первую попытку, используя этот подход. Я использую только один образец и записываю его как непрерывные 16-е ноты в темпе 120 ударов в минуту. Но по какой-то причине он играет со скоростью 240 ударов в минуту.
Сначала я проверил свой код, чтобы получить время 16-й (наносекундной) ноты в темпе X. Он проверяется.
private void setPeriod()
{
period=(int)((1/(((double)TEMPO)/60))*1000);
period=(period*1000000)/4;
Log.i("test",String.valueOf(period));
}
Затем я проверил, что мой код для получения времени воспроизведения моего буфера на частоте 44100 кГц в наносекундах и это правильно.
long bufferTime=(1000000000/SAMPLE_RATE)*buffSize;
Так что теперь я думаю, что звуковая дорожка воспроизводится с частотой, отличной от 44100. Может быть, 96000 кГц, что объясняет удвоение скорости. Но когда я создаю audioTrack, он действительно был установлен на 44100 кГц.
окончательный int SAMPLE_RATE установлен на 44100
buffSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
track = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
buffSize,
AudioTrack.MODE_STREAM);
Поэтому я не понимаю, почему мой темп удваивается. Я запустил отладку, чтобы сравнить прошедшее время audioTrack с прошедшим системным временем, и кажется, что аудиодорожка действительно воспроизводится в два раза быстрее, чем должна быть. Я смущен.
Просто чтобы убедиться, что это моя игровая петля.
public void run() {
// TODO Auto-generated method stub
int buffSize=192;
byte[] output = new byte[buffSize];
int pos1=0;//index for output array
int pos2=0;//index for sample array
long bufferTime=(1000000000/SAMPLE_RATE)*buffSize;
long elapsed=0;
int writes=0;
currTrigger=trigger[triggerPointer];
Log.i("test","period="+String.valueOf(period));
Log.i("test","bufferTime="+String.valueOf(bufferTime));
long time=System.nanoTime();
while(play)
{
//fill up the buffer
while(pos1<buffSize)
{
output[pos1]=0;
if(currTrigger&&pos2<sample.length)
{
output[pos1]=sample[pos2];
pos2++;
}
pos1++;
}
track.write(output, 0, buffSize);
elapsed=elapsed+bufferTime;
writes++;
//time passed is more than one 16th note
if(elapsed>=period)
{
Log.i("test",String.valueOf(writes));
Log.i("test","elapsed A.T.="+String.valueOf(elapsed)+" elapsed S.T.="+String.valueOf(System.nanoTime()-time));
time=System.nanoTime();
writes=0;
elapsed=0;
triggerPointer++;
if(triggerPointer==16)
triggerPointer=0;
currTrigger=trigger[triggerPointer];
pos2=0;
}
pos1=0;
}
}
}