Я не уверен, что понимаю точные ограничения, которые у вас есть для реализации решения, но кажется, что самый простой способ сделать это - сохранить аудиоданные в буфере при первом воспроизведении файла. Затем, если пользователю требуется больше итераций (полных или частичных), просто переписайте данные, которые вы кэшировали, обратно в SourceDataLine нужное количество раз.
Вот ссылка на проигрыватель образцов звуковых файлов (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;
}
}
}
Надеюсь, это поможет!