Как правильно зациклить раздел из песни?

8

Я программирую небольшой Music Engine для своей игры на C # и XNA, и одним из аспектов этого является возможность зацикливания фрагмента песни. Например, моя песня имеет вступление, и когда песня достигла конца (или любой другой конкретной точки), она возвращается туда, где вступление только что закончилось. (A - B - B - B ...)

Сейчас я использую IrrKlank, который работает отлично, без пробелов, но у меня проблема:

Точка, где нужно прыгать назад, немного неточна. Вот пример кода:

public bool Passed(float time)
    {
        if ( PlayPosition >= time )
            return true;
        return false;
    }
//somewhere else
if( song.Passed( 10.0f ) )
   song.JumpTo( 5.0f );

Теперь проблема в том, что песня проходит 10 секунд, но проигрывает несколько миллисекунд до 10.1f или около того, а затем переходит на 5 секунд. Это не так драматично, но очень неправильно для моих нужд. Я попытался исправить это так:

public bool Passed( float time )
{
      if( PlayPosition + 3 * dt >= time && PlayPosition <= time )
             return true;
      return false;
}

(dt - время дельты, время, прошедшее с последнего кадра)

Но я не думаю, что это хорошее решение для этого.

Я надеюсь, что вы можете понять мою проблему (и мой английский, yay / o /) и помочь мне :)

Teflo
источник
Вы можете выбрать между потоковой передачей звука или загрузкой всего сразу?
тесселоде
Я думаю, что это возможно. В данный момент я загружаю полную песню, потому что я думал, что прыгать в песне будет быстрее. Я пытаюсь использовать многопоточность, чтобы решить эту проблему, но мне все еще не повезло: /
Teflo
Попробуйте вместо этого транслировать звук. В конце концов, он должен быть в состоянии загрузить небольшой фрагмент песни почти мгновенно.
Тесселоде
Как закодирована ваша песня?
michael.bartnett
Возможно, вместо использования «пройдено», вы можете добавить квесты (например, события), которые выполняют функцию обратного вызова. Я не знаю, как ты управляешь своим временем. Но не могли бы вы использовать количество прочитанных байтов и сравнить его с общим количеством байтов и перевести его в точное время? Вы должны быть в состоянии рассчитать, сколько данных читается за одну секунду. Хотя я не знаю, как быстро это будет. Но, может быть, тогда вы могли бы прочитать время более точно.
Сидар

Ответы:

3

На мой взгляд, более простое и обычное решение состоит из двух разных треков: вступления и цикла. Тогда единственная проблема - определить, когда вступление заканчивается (довольно просто, хотя и не совсем точно, если использовать 30fps). Затем второй трек можно воспроизвести с включенным циклом.

Таким образом, вы уменьшаете ошибки при воспроизведении до небольшой задержки при первом запуске цикла, а не каждый раз, когда необходимо перематывать часть цикла.

Elideb
источник
0

Идеальным решением было бы знать заранее, какие части песни должны быть загружены рядом в буфер. Каждый «раздел» A-B-C будет иметь время начала и окончания, и это будет ваша потоковая система более низкого уровня, которая будет загружать правильные части файла в правильном порядке. Для этого вам понадобится фиксированный битрейт, и может быть довольно сложно найти, где в файле нужно перейти к следующему.

Я быстро взглянул на сайт irrKlang, и они могут похвастаться возможностью написать свои собственные устройства чтения / декодирования форматов файлов для расширения движка с ним, так что вы можете попробовать это.

Существует также учебник здесь , чтобы отменить доступ к файлам - вы могли бы дать свою оригинальную идею выстрел, или вы можете смешать его с несколькими звуками , как сказал Elideb. Вы можете расширить свой класс CMyReadFile, чтобы иметь доступ к нескольким файлам (таким как PartA.wav, PartB.wav, PartC.wav), и вы можете переопределить метод read, вместо того, чтобы просто:

return (s32)fread(buffer, 1, sizeToRead, File);

Вы могли бы сделать что-то вроде:

switch(CurrentSectionToPlay)
{
case A:
    return (s32)fread(buffer, 1, sizeToRead, FileA);
case B:
    return (s32)fread(buffer, 1, sizeToRead, FileB);
}

Это означает, что песня будет легко менять раздел без синхронизации Plays & Stops.

Джонатан Коннелл
источник