AC97snd - плеер MP3 и WAV
-
Это уже к Serge. Зайдет на форум - чего-нибудь отпишет.
Вылетает здесь. Уровни громкости и баланс каналов приводятся к диапазону 0,-10000.
Code: Select all
Infinity.asm
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
locals
_600 dd ?
_32767 dd ?
state rb 108
endl
mov [_600], 0x44160000 ;600.0
mov [_32767], 32767
lea ebx, [state]
fnsave [ebx]
movq mm0, qword [l_vol]
pminsw mm0, qword [vol_max] <<< SSE
pmaxsw mm0, qword [vol_min] <<< SSE
movq qword [l_vol], mm0
movq qword [edx+STREAM.l_vol], mm0
Я думал об общем количестве вылетов, если их немного, получится их обойти?
В какой строке вылетает?
Вылетает где то в фрагменте?
Это первый вылет?
Их будет ещё много?
В какой строке вылетает?
Вылетает где то в фрагменте?
Это первый вылет?
Их будет ещё много?
Это код регулировки громкости. Будет вылетать при первом вызове SND_SETVOLUME. Конткетно - здесь pminsw mm0, qword [vol_max]. Обойти не получится, только переписать.
Сейчас читаю.
PMINSW compares each pair of words in the two source operands, and for each pair it stores the minimum value in the destination register.
Как я понимаю сравнивает два упакованных слова.
Т.е. если написать проверку на поддержку команд PMINSW, PMAXSW и заглушку для их замены должно заработать?
Как думаешь насколько строк потянут заглушки?
Дальше исключений не будет?
PMINSW compares each pair of words in the two source operands, and for each pair it stores the minimum value in the destination register.
Как я понимаю сравнивает два упакованных слова.
Т.е. если написать проверку на поддержку команд PMINSW, PMAXSW и заглушку для их замены должно заработать?
Как думаешь насколько строк потянут заглушки?
Дальше исключений не будет?
Будет работать. Что требуется:
Code: Select all
if(l_vol > 0)
l_vol = 0;
else if(l_vol < -10000)
l_vol = -10000;
if(r_vol > 0)
r_vol = 0;
else if(r_vol < -10000)
r_vol = -10000;
if(pan > 10000)
pan = 10000;
else if( pan < -10000)
pan = -10000;
stream->pan = pan;
if( pan > 0)
{
l_vol-= pan;
if(l_vol < -10000)
l_vol = -10000;
}
else
{
r_vol+= pan;
if(r_vol < -10000)
r_vol = -10000;
}
calc_amp:
далее по-тексту
Спасибо попробую заменить и запустить.
Сделал замену, но останавливается в начале проигрывания файла без ошибок в доске отладки.
Точнее ac97snd открывается начинает идти ползунок и останавливается с небольшим смещением от начала, при этом никаких звуков нет.
Если после этого нажать stop, а потом play картина повторяется.
Точнее ac97snd открывается начинает идти ползунок и останавливается с небольшим смещением от начала, при этом никаких звуков нет.
Если после этого нажать stop, а потом play картина повторяется.
- Attachments
-
-
infinity.7z (9.07 KiB)
- infinity.asm модифицированный
Downloaded 475 times
infinity.obj модифицированный
pminmaxsw.inc подмена функций - infinity.asm модифицированный
-
Не срабатывает IRQ. Поставь отладочное сообщение в обработчике. Каждый раз по завершении обработки буфера должно генерироваться прерывание.
Подскажи точнее где ставить?
В каком файле?
В каком месте?
В каком файле?
В каком месте?
В аудиодрайвере, в данном случае sb16.asm (так он вроде бы называется). В обработчике прерываний (в начале например) ставишь что-то вроде:
После вызова Рlay драйвера на доске отладке должна появиться автоматная очередь соответствующих сообщений.
Code: Select all
mov esi, strIRQ
call SysMsgBoardStr
Поставил отладочное сообщение в infinity.asm
@@:
cmp eax, SND_OUT
jne @F
if DEBUG
mov esi, msgSNDOUT
call SysMsgBoardStr
end if
mov eax, [ebx+4]
stdcall wave_out, edx,eax,[ebx+8]
ret
под эмулятором в самом деле очередь сообщений по выводу звука, а в реальной машине где то 20 шт. и конец
и ещё подметил в конце отладки в эмуляторе строка о закрытии программы а в реальной отладке такой строки нет.
@@:
cmp eax, SND_OUT
jne @F
if DEBUG
mov esi, msgSNDOUT
call SysMsgBoardStr
end if
mov eax, [ebx+4]
stdcall wave_out, edx,eax,[ebx+8]
ret
под эмулятором в самом деле очередь сообщений по выводу звука, а в реальной машине где то 20 шт. и конец
и ещё подметил в конце отладки в эмуляторе строка о закрытии программы а в реальной отладке такой строки нет.
Вообще-то под обработчиком прерываний я имел ввиду вот эту функцию.
Ну да ладно всё равно понятно, что прерывание не срабатывает как надо, а это скорее всего следствие неправильной его обработки. Т.е. вероятно, что обработчик как следует не оповещает устройство об окончании обработки прерывания.
Ну да ладно всё равно понятно, что прерывание не срабатывает как надо, а это скорее всего следствие неправильной его обработки. Т.е. вероятно, что обработчик как следует не оповещает устройство об окончании обработки прерывания.
Unduing
Во-первых проверь правильно ли определился базовый порт (sb_base_port).
Во-вторых у тебя вроде бы Vibra16? Если так то ALSA тебе в помощь (путь alsa-driver-x.x.x\alsa-kernel\isa\sb).
Там в модуле sb16_main.c обработчик выглядит так:
В зависимости от переменной status прерывание может быть 8-ми или 16-ти битным.
Статус читается вот этой процедурой из модуля sb_mixer.c:
В sb.h можно найти процедуры snd_sb_ack_8bit и snd_sb_ack_16bit.
В текущем обработчике прерываний драйвера для sb16 есть реализация только snd_sb_ack_16bit, вот она
Статус не проверяется, может быть и в этом проблема, может и не в этом нужно проверить.
Если базовый порт всё-таки определяется верно, попробуй добавить к обработчику чтение статуса:
и обработку 8 битного прерывания:
StallExec можно взять здесь.
Да и ещё наверное лучше будет сообщать о завершении обработки прерывания в конце, а не в начале обработчика.
Во-первых проверь правильно ли определился базовый порт (sb_base_port).
Во-вторых у тебя вроде бы Vibra16? Если так то ALSA тебе в помощь (путь alsa-driver-x.x.x\alsa-kernel\isa\sb).
Там в модуле sb16_main.c обработчик выглядит так:
Code: Select all
irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id)
{
struct snd_sb *chip = dev_id;
unsigned char status;
int ok;
spin_lock(&chip->mixer_lock);
status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS);
spin_unlock(&chip->mixer_lock);
if ((status & SB_IRQTYPE_MPUIN) && chip->rmidi_callback)
chip->rmidi_callback(irq, chip->rmidi->private_data);
if (status & SB_IRQTYPE_8BIT) {
ok = 0;
if (chip->mode & SB_MODE_PLAYBACK_8) {
snd_pcm_period_elapsed(chip->playback_substream);
snd_sb16_csp_update(chip);
ok++;
}
if (chip->mode & SB_MODE_CAPTURE_8) {
snd_pcm_period_elapsed(chip->capture_substream);
ok++;
}
spin_lock(&chip->reg_lock);
if (!ok)
snd_sbdsp_command(chip, SB_DSP_DMA8_OFF);
snd_sb_ack_8bit(chip);
spin_unlock(&chip->reg_lock);
}
if (status & SB_IRQTYPE_16BIT) {
ok = 0;
if (chip->mode & SB_MODE_PLAYBACK_16) {
snd_pcm_period_elapsed(chip->playback_substream);
snd_sb16_csp_update(chip);
ok++;
}
if (chip->mode & SB_MODE_CAPTURE_16) {
snd_pcm_period_elapsed(chip->capture_substream);
ok++;
}
spin_lock(&chip->reg_lock);
if (!ok)
snd_sbdsp_command(chip, SB_DSP_DMA16_OFF);
snd_sb_ack_16bit(chip);
spin_unlock(&chip->reg_lock);
}
return IRQ_HANDLED;
}
Статус читается вот этой процедурой из модуля sb_mixer.c:
Code: Select all
unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg)
{
unsigned char result;
outb(reg, SBP(chip, MIXER_ADDR));
udelay(10);
result = inb(SBP(chip, MIXER_DATA));
udelay(10);
#ifdef IO_DEBUG
snd_printk(KERN_DEBUG "mixer_read 0x%x 0x%x\n", reg, result);
#endif
return result;
}
Code: Select all
static inline void snd_sb_ack_8bit(struct snd_sb *chip)
{
inb(SBP(chip, DATA_AVAIL));
}
static inline void snd_sb_ack_16bit(struct snd_sb *chip)
{
inb(SBP(chip, DATA_AVAIL_16));
}
Code: Select all
225 mov edx,[sb_base_port] ;tell the DSP that we have processed IRQ
226 add dl,0xF ;0xF for 16 bit sound, 0xE for 8 bit sound
227 in al,dx ;for non-stop sound
Статус не проверяется, может быть и в этом проблема, может и не в этом нужно проверить.
Если базовый порт всё-таки определяется верно, попробуй добавить к обработчику чтение статуса:
Code: Select all
mov edx,[sb_base_port]
add dl,0xF
mov al, 0x4
out dx,al
inc dl
mov eax, 10000 ; wait 10 ms
call StallExec
in al,dx
push eax
mov eax, 10000 ; wait 10 ms
call StallExec
pop eax
Code: Select all
mov edx,[sb_base_port] ;tell the DSP that we have processed IRQ
add dl,0xE ;0xF for 16 bit sound, 0xE for 8 bit sound
in al,dx ;for non-stop sound
StallExec можно взять здесь.
Да и ещё наверное лучше будет сообщать о завершении обработки прерывания в конце, а не в начале обработчика.
Asper
Спасибо за подробный ответ.
Ты был прав поставил отладочное сообщение в sb16.asm в самом начале sb_irq, нет не одного входа в обработчик, не знаю почему.
1. Порт определился правильно.
2. Да у меня Vibra 16 вставленная в isa slot
Логи запуска
С предыдущим постом ещё разбираюсь.
Спасибо за подробный ответ.
Ты был прав поставил отладочное сообщение в sb16.asm в самом начале sb_irq, нет не одного входа в обработчик, не знаю почему.
1. Порт определился правильно.
2. Да у меня Vibra 16 вставленная в isa slot
Логи запуска
С предыдущим постом ещё разбираюсь.
Who is online
Users browsing this forum: No registered users and 2 guests