AC97snd - плеер MP3 и WAV

Processing, playback of audio and video
  • Вылетает здесь.

    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
    
    Уровни громкости и баланс каналов приводятся к диапазону 0,-10000.
  • Я думал об общем количестве вылетов, если их немного, получится их обойти?
    В какой строке вылетает?
    Вылетает где то в фрагменте?
    Это первый вылет?
    Их будет ещё много?
  • Это код регулировки громкости. Будет вылетать при первом вызове 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 и заглушку для их замены должно заработать?
    Как думаешь насколько строк потянут заглушки?
    Дальше исключений не будет?
  • Будет работать. Что требуется:

    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 картина повторяется.
    Attachments
    infinity.7z (9.07 KiB)
    infinity.asm модифицированный
    infinity.obj модифицированный
    pminmaxsw.inc подмена функций
    Downloaded 470 times
  • Не срабатывает IRQ. Поставь отладочное сообщение в обработчике. Каждый раз по завершении обработки буфера должно генерироваться прерывание.
  • Подскажи точнее где ставить?
    В каком файле?
    В каком месте?
  • В аудиодрайвере, в данном случае sb16.asm (так он вроде бы называется). В обработчике прерываний (в начале например) ставишь что-то вроде:

    Code: Select all

    mov    esi, strIRQ
    call     SysMsgBoardStr
    
    После вызова Рlay драйвера на доске отладке должна появиться автоматная очередь соответствующих сообщений.
  • Поставил отладочное сообщение в 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 шт. и конец
    и ещё подметил в конце отладки в эмуляторе строка о закрытии программы а в реальной отладке такой строки нет.
  • Вообще-то под обработчиком прерываний я имел ввиду вот эту функцию.
    Ну да ладно всё равно понятно, что прерывание не срабатывает как надо, а это скорее всего следствие неправильной его обработки. Т.е. вероятно, что обработчик как следует не оповещает устройство об окончании обработки прерывания.
  • Unduing
    Во-первых проверь правильно ли определился базовый порт (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;
    }
    
    В зависимости от переменной status прерывание может быть 8-ми или 16-ти битным.

    Статус читается вот этой процедурой из модуля 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;
    }
    
    В sb.h можно найти процедуры snd_sb_ack_8bit и snd_sb_ack_16bit.

    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));
     }
    В текущем обработчике прерываний драйвера для sb16 есть реализация только snd_sb_ack_16bit, вот она

    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
    
    и обработку 8 битного прерывания:

    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
    Логи запуска

    С предыдущим постом ещё разбираюсь.
  • Who is online

    Users browsing this forum: No registered users and 1 guest