Я не уверен, что я понимаю точные ограничения, которые у вас есть для реализации решения, но кажется, что самый чистый способ сделать это - сохранить аудиоданные в буфере при первом воспроизведении файла. Затем, если для пользователя требуется больше итераций (полных или частичных), просто перепишите данные, которые вы кэшировали обратно в SourceDataLine, необходимое количество раз.
link Образец звукового файла (PCM), который должен быть очень легко модифицировать (или просто учиться). Я также взломал какой-то (примечание: непроверенный) код, который просто показывает логику, описанную выше: (Возможно, вы также захотите изменить то, что у меня есть, чтобы соответствовать правилам, касающимся только записи фрагментов данных, размер которых несколько от размера рамы.)
public void playSoundFile(SourceDataLine line, InputStream inputStream, AudioFormat format, long length, float times)
{
int index = 0;
int size = length * format.getFrameSize();
int currentSize = 0;
byte[] buffer = new byte[size];
AudioInputStream audioInputStream = new AudioInputStream(inputStream, format, length);
while (index < size)
{
currentSize = audioInputStream.read(buffer, index, size - index);
line.write(buffer, index, currentSize);
index += currentSize;
}
float currentTimes = 1.0;
while (currentTimes < times)
{
float timesLeft = times - currentTimes;
int writeBlockSize = line.available();
index = 0;
if (timesLeft >= 1.0)
{
while (index < size)
{
currentSize = ((size - index) < writeBlockSize) ? size - index : writeBlockSize;
line.write(buffer, index, currentSize);
index += currentSize;
}
currentTimes += 1.0;
}
else
{
int partialSize = (int)(timesLeft * ((float) size) + 0.5f);
while (index < partialSize)
{
currentSize = ((partialSize - index) < writeBlockSize) ? partialSize - index : writeBlockSize;
line.write(buffer, index, currentSize);
index += currentSize;
}
currentTimes += timesLeft;
}
}
}
Надеюсь, что это поможет!
I есть несколько вопросов - как мне «привязать» цикл к моей существующей DataLine, которую я использую? Что делать с клипом? - как отправить это в SourceDataLine? – Tim
Он будет автоматически присоединен к вашей текущей активной DataLine, клип будет похож на экземпляр другого игрока, вы можете начать или остановить его всякий раз, когда захотите. Вы можете запросить кепки, чтобы увидеть, сколько из них может быть воспроизведено одновременно. При необходимости вы можете определить очередь. Но я не рекомендую смешивать себя. –
Я попробую, но не уверен, что он будет работать с dataline, как мой код существует. благодаря – Tim