Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
А что значит отсутствие буфера?
Не хрипит / не задерживается ли звук при игре по wi-fi?
Не происходит ли через 10-20 минут сессии рассинхронизации играющих?
чтобы играть через интернет. И она успешно с этим справилась?
без этого буфера в Music Over The World Tool можно без проблем играть на темпе 120-140между Москвой и Сан-Франциско.
как именно оно работает без буферизации, когда нового звука от удалённого участника ещё не поступалоПросто ASIO-драйвер callback'ом (44100 / buffSize) раз в секунду вызывает огроомную функцию, в которой написано в т.ч. следующее:
#define MAX_NET_USERS 8 // максимальное число удаленных участников музыкальной онлайн-сессии; в первом релизе сделать 8
for(int i = 0; i < MAX_NET_USERS; i++)
{
// послать смикшированные сэмплы
if(nSend[i] == 1)
{
NetSend((unsigned char*)(asioDriverInfo.bufferInfos[OutputCh].buffers[index]), (unsigned char*)(asioDriverInfo.bufferInfos[OutputCh+1].buffers[index]), buffSize, i);
}
// считать сетевые данные
if(NetReceive((unsigned char*)(BigLeft), (unsigned char*)(BigRight), buffSize, i) == 0)
{
ClientCounter++;
}
}
int NetReceive(unsigned char *Left, unsigned char *Right, int MaxSamples, int ClientIndex)
{
//...
if(NetReceive_real(ReceivedFrame, (2048 * 4 * 2) + 4 + 4, ClientIndex) == 0)
{
for(int NewBufPos = 0; NewBufPos < MaxSamples; NewBufPos++)
{
// смикшировать очередной сэмпл левого канала
// смикшировать очередной сэмпл правого канала
//...
}
}
else
{
//...
return -1;
}
return 0;
}
int NetReceive_real(unsigned char * data, int maxdatasize, int ClientIndex)
{
struct sockaddr_in RecvAddr;
int fromlen = sizeof(struct sockaddr_in);
if(recvfrom(MySocket[ClientIndex], (LPSTR)data, maxdatasize, 0, (sockaddr*)&RecvAddr, &fromlen) >= 0)
{
PeerTableSetLastUpdateTime(RecvAddr.sin_addr.s_addr, MySystemTime);
return 0; // если данные с сокета успешно считаны то возвращаем ноль
}
else
{
return -1; // иначе НАДО ВОЗВРАТИТЬ -1(!)
}
}
Какие расстояния подразумевается под словом «интернет» здесьХм, один человек был в этом-же городе, где и я, и еще один был в соседнем городе за 50 км.
В частности, я сомневаюсь что без этого буфера в Music Over The World Tool можно без проблем играть на темпе 120-140 между Москвой и Сан-Франциско.Как я уже написал, чудес не бывает. Программа не может уменьшить пинг между двумя удаленными компьютерами. Так что если пинг будет миллисекунд 80, то проблемы будут. Но уж точно не по вине программы, суть то в этом.
То есть если пакет пришёл — он микшируется со следующим звуковым фреймом на playback, иначе — вместо канала пустота, верно?как именно оно работает без буферизации, когда нового звука от удалённого участника ещё не поступалоПросто ASIO-драйвер callback'ом (44100 / buffSize) раз в секунду вызывает огроомную функцию, в которой написано в т.ч. следующее:
Без этого буфера в Music Over The World Tool можно без проблем играть на темпе 120-140.
Как я уже написал, чудес не бывает.Всё понимаю, просто исходная формулировка показалась мне эээ неточной :)
То есть если пакет пришёл — он микшируется со следующим звуковым фреймом на playback, иначе — вместо канала пустота, верноВерно. А разделение клиентов друг от друга осуществляется за счет разных портов приема. Причем тут тоже был интересный подводный камень. Чтобы в распределенной p2p-сети два разных участника не слали данные в один и тот же порт, каждый участник шлет данные в порт, индекс которого является позицией абсолютного четырёхбайтового значения своего ip-адреса в отсортированной по возрастанию таблице ip-адресов всех участников сессии.
Чтобы в распределенной p2p-сети два разных участника не слали данные в один и тот же порт, каждый участник шлет данные в порт, индекс которого является позицией абсолютного четырёхбайтового значения своего ip-адреса в отсортированной по возрастанию таблице ip-адресов всех участников сессии.Что если два участника из трёх находятся в одной виртуальной подсети?
вначале приведённый код выдаст несколько сеансов тишины
весь дальнейший звук удалённого участника будет задерживаться
буферизация в вашей системе уже есть, просто вы об этом не догадывалисьДа, как я уже говорил, у меня есть опыт работы с UDP, и это я знал. Но единственной мыслью было периодически очищать буфер сокета. Только запамятовал, можно ли получить статистику о количестве пришедших пакетов на сокет? Если можно, то может стоит очищать сокет, если скопилось больше одного пакета. Хм.
Что если два участника из трёх находятся в одной виртуальной подсетиА можно на примере, не совсем понятно что такое «виртуальная подсеть» в данном контексте?
Но единственной мыслью было периодически очищать буфер сокета.Каждый раз когда при воспроизведении будет пропускаться хотя бы один пакет (очищенный), будет происходить негладкая склейка звука, то есть щелчок.
Только запамятовал, можно ли получить статистику о количестве пришедших пакетов на сокет?Честно скажу — не знаю :) И узнавать не советую, так как всё равно по вышеописанным причинам (склейка, пропуск пакетов, потери пакетов) нужно будет делать нормальный jitter-буфер, читающий из сокета в неблокирующемся режиме. И кстати там можно и multiplexing будет спокойно сделать через один порт.
А можно на примере, не совсем понятно что такое «виртуальная подсеть» в данном контексте?Например, если они вдвоём сидят за одним NAT'ом и получают один и тот же публичный IP-адрес.
всё равно по вышеописанным причинам (склейка, пропуск пакетов, потери пакетов) нужно будет делать нормальный jitter-буферВсе правильно, можно улучшить эту часть в моей программе. Но, по-первых, у меня проблем с потерями пакетов не возникало. Во-вторых, в комментариях выше были указаны замечательные ссылки на программы Jamulus и Soundjack, о которых я не знал. Судя по описанию это как раз то, что нужно. В случае проблем с моей программой буду использовать их.
Например, если они вдвоём сидят за одним NAT'ом и получают один и тот же публичный IP-адрес.В лучшем случае первый подключившийся из виртуальной сети к хосту во внешней сети будет передавать свои аудио данные, а сам слышать ничего не будет. Ибо с NAT'ом я не разбирался и ничего специально для этого не писал.
Все правильно, можно улучшить эту часть в моей программе. Но, по-первых, у меня проблем с потерями пакетов не возникало.Понятно. Другими словами, озвученное
главное отличие программы Music Over The World Tool от Netduettoоказалось не супер-преимуществом
А что значит отсутствие буфера? Это значит что собеседник услышит ваш аккорд на несколько миллисекунд раньше., а скорее недодуманностью/недоработкой в силу недостаточного тестирования. Бывает.
В лучшем случае первый подключившийся из виртуальной сети к хосту во внешней сети будет передавать свои аудио данные, а сам слышать ничего не будет.Не-не, в лучшем случае всё будет работать ОК. А вот в худшем — два клиента за NAT будут посылать пакеты в один и тот же порт «нормального» третьего участника. Получится что-то типа dubstep :)
Понятно. Другими словами, озвученное оказалось не супер-преимуществом, а скорее недодуманностью/недоработкой.Не совсем так. Во-первых, я нигде не писал об этом как о «супер-преимуществе», я лишь описал это в списке вещей, «которые мне показались интересными в процессе разработки программы». Даже вообще не называл это преимуществом, говоря «отличие в плане буферизации». Во-вторых, при качественном интернете, или в локальной сети, это действительно преимущество, а не недоработка. Ибо реально минимизирует задержку.
Конечно, чудес не бывает, и за все приходится платить — нужно устанавливать на всех компьютерах участников одинаковый размер входных и выходных буферов ASIO-драйверов.Это необязательное ограничение.
Но тогда не было ни ASIOКстати вполне себе было :)
Музыкальные репетиции: теперь и через интернет