Вот простейший код, хочу разобраться со звуком.. но при переключении буферов возникают щелчки длит. 0.1 сек... тема заезженая, но в сети ничего толкового не нашёл Код (Text): procedure PlaySound(); var i: dword; event_: dword; t: bool; si: TSystemInfo; mem: pointer; Format: TWaveFormatEx; WaveOut: hWaveOut; WaveHdr: array [0..1] of TWaveHdr; begin Format.wFormatTag:=WAVE_FORMAT_PCM; Format.nChannels:=1; Format.nSamplesPerSec:=11025; Format.cbSize:=0; Format.wBitsPerSample:=8; Format.nBlockAlign:=Format.nChannels*(Format.wBitsPerSample div 8); Format.nAvgBytesPerSec:=Format.nSamplesPerSec*Format.nBlockAlign; event_:=CreateEvent(nil, false, false, nil); GetSystemInfo(si); mem:=VirtualAlloc(nil, (16384*4+si.dwPageSize-1) div si.dwPagesize*si.dwPageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE); ZeroMemory(@WaveHdr, SizeOf(WaveHdr)); WaveHdr[0].lpData:=mem; WaveHdr[0].dwBufferLength:=16384; WaveHdr[1].dwBufferLength:=16384; WaveHdr[1].lpData:=pointer(dword(mem)+WaveHdr[0].dwBufferLength); waveOutOpen(@WaveOut, WAVE_MAPPER, @Format, event_, 0, CALLBACK_EVENT); waveoutprepareheader(WaveOut, @WaveHdr[0], SizeOf(TWaveHdr)); waveoutprepareheader(WaveOut, @WaveHdr[1], SizeOf(TWaveHdr)); for i:=0 to 16384*2-1 do begin if t then byte(pointer(dword(mem)+i)^):=0 else byte(pointer(dword(mem)+i)^):=255; t:=not t; end; i:=0; ResetEvent(Event_); repeat WaveOutWrite(WaveOut, @WaveHdr[i], SizeOf(TWaveHdr)); i:=i xor 1; WaitForSingleObject(Event_, INFINITE); until (false);
Такая весчь равносильна мерцанию картинки при перерисовке без заднего буфера кадра. ИМХО, решение проблемы - свести эти 2 буфера в один, размером 32кб (если я правильно понял код) и отправлять на воспроизведение единым куском. ЗЫЖ а как можно в белом шуме различить щелчки? [+]: также, можно поставить зацикленное воспроизведение. Только вот блин, забыл как он ставится. Вроде как парамами в waveOutOpen. Снимается с waveOutBreakLoop, это-то я вроде помню... Отыщу свои "творения" - отпишусь.
Прикол в том что "щёлкает" даже если буфер пустой... я уже писал подобную прогу.. практичеки такую же и без этих "артефактов".. эх.. найти бы её ещё.. [+]: сделал так: Код (Text): WaveHdr[0].lpData:=mem; WaveHdr[0].dwBufferLength:=32768; WaveHdr[1].dwBufferLength:=32768; WaveHdr[1].lpData:=mem; //pointer(dword(mem)+WaveHdr[0].dwBufferLength); ...та же хрень
Вроде и буферы выровнены всё как в туторе, ничего не могу понять... может у кого работающий примерчик найдётся?
Для Win нет, но я писал в свое время WAV-плеер под DOS real-mode через DMA. У меня была похожая проблема. Создавались 2 буфера, и свуковой карте давался один буфер. Пока она его играла, подгружались данные во второй. Срабатывало прерывание об окончании буфера - я переключал карточку на второй буфер. Тут и возникали щелчки. Решение было простое: создавать один буфер из двух частей (каждая размером W) и грузить сразу обе части. И инициализировать звуковую на размер воспроизведение по размеру W. А DMA настроил на закольцованную отдачу карточке и подгружал по W байт в неактивную половину буфере при получении прерывания. Может чем поможет. Но это чистый DOS.
Exp10der А в момент окончания второго буфер происходит подгрузка в оба сразу? И не "щелкает"? Странно...
Xerx Не совсем: ставишь играть первый буфер пишешь во второй - соотв. играет второй - пишешь в первый и т. д.
Возможной причиной щелчков может быть слишком разный уровень сигнала в конце первого сэмпла и начале второго (или если в первом сэмпле шло нарастание, а во втором - убывание - тогда получается короткий по времени и большой по амплитуде разовый импульс, т.е. щелчок). Даже при простом склеивании в звуковом редакторе за гладкостью сигнала на склейке приходилось следить.
Если ты разобрался, выложи пожалуйста исходник. Я полдня пытаюсь понять похожие грабли, причем щелкает как начало воспроизведения, так и окончание воспроизведения Внутри - все отлично... Края массива щелкают.... причем если весь массив забит 0-лями, то щелчки абсолютно такие-же.... Ядреные и громкие....