Niedawnym czasem zakupiłem okazyjnie na znanym_serwisie_aukcyjnym® interface muzyczny e-mu1820m.
Do pracy używam Linuksa (ostatnio Kubuntu 10.10). Zaś ponieważ rzeczy robię w standardzie audio (44.1 kHz) musiałem się nieco nagimnastykować zanim E-mu zapracowało tak jak chciałem. …no prawie tak.
Pierwsza podgórka
Karta na dzień dobry wymaga doinstalowania firmware. Niestety repozytorium Kubuntu nie chce w tym temacie współpracować. Zatem trzeba to zrobić ręcznie. Z http://rpm.pbone.net ściągamy sobie i instalujemy dowolne alsa-firmware które zawiera pliki emu10k1. Ja wybrałem emu1010-firmware-1.0.23-2pclos2010.i586.rpm. Erpeema trzeba potraktować alienem.
alien -i emu1010-firmware*
Inny, równie prosty sposób to ściągnięcie sobie tych plików (skądkolwiek) i ręczne wrzucenie ich do katalogu /lib/firmware/emu, który po tej operacji powinien wyglądać tak:
audio_dock.fw
emu0404.fw
emu1010b.fw
emu1010_notebook.fw
hana.fw
micro_dock.fw
Później restart systemu i ALSA powinna działać w miarę prawidłowo. Sprawdzamy to uruchamiając alsamixer.
Ustawiamy przy okazji Clock In: [44100] oraz konfigurujemy sobie wejścia /wyjścia tak jak nam serce podpowiada.
Druga przeszkoda
Zadowoleni uruchamiamy qjackctl i próbujemy go skonfigurować do obsługi emu:
[v] Realtime
[v] No Memory Lock
[v] Soft ModeFrames/Period: [512] na początek
Sample Rate: [44100]
Periods/Buffer: [2]
Port Maximum: [512]
Timeout (msec): [500]
Dither: [None]
Audio: [Duplex]
Input Device: [hw:0,2] (Multichannel Capture/PT Playback)
Output Device: [hw:0,3] (Multichannel Playback)
reszta: [default]
I… niespodzianka. Po wystartowaniu jacka, mimo iż wszędzie w ustawieniach mamy 44100 Hz, to playback pracuje przy 48000 Hz. Ha!
Po wielu bojach i kombinacjach wyszło na to, że trzeba trochę zahakować alsa-drivers. Nie ma wyjścia, zobacz https://bugtrack.alsa-project.org/wiki/wikka.php?wakka=emu&show_comments=1 i zwróć uwagę na fragment „multichannel playback is currently broken”.
Jednak my się tym zupełnie nie przejmujemy. Zakasujemy rękawy i bierzemy się do roboty.
Pliki do ściągnięcia
Kernel
https://launchpad.net/~abogani/+archive/ppa/+sourcepub/1258598/+listing-archive-extra
Z tej strony ściągamy takie lub podobne pliki (w zależności od architektury systemu możesz potrzebować wersji dla amd)
- linux-image-2.6.33–29-realtime_2.6.33–29.1_i386.deb (27.5 MiB)
- linux-headers-2.6.33-29_2.6.33–29.1_all.deb (9.6 MiB)
- linux-headers-2.6.33–29-realtime_2.6.33–29.1_i386.deb (676.0 KiB)
Instalujemy to po kolei dwukrotnie klikając w każdy plik. Następnie restart systemu i… jeśli linux wstanie a uname zwróci nam prawidłową wartość — przechodzimy do następnego kroku.
uname -r
2.6.33-29-realtime
Dla pewności sprawdzamy czy /usr/src/linux wskazuje na prawidłową wersję linux-headers. W naszym przypadku powinno być:
ls -l /usr/src
linux -> linux-headers-2.6.33–29-realtime
Opcja B — FIXME
configure FIX
9439 if test ! -f include/trace/events/asoc.h; then
9440 mkdir -p include/linux include/asm include/media
9441 mkdir -p include/linux/regulator include/linux/usb include/pcmcia
9442 mkdir -p include/trace/events
9443 if test -z "#include \"trace_events_asoc_compat.h\"
9444 " ; then
9445 echo "Creating a dummy <trace/events/asoc.h>..."
9446 touch include/trace/events/asoc.h
9447 else
9448 echo "Creating <trace/events/asoc.h>..."
9449 echo "#include \"trace_events_asoc_compat.h\"
9450 " > include/trace/events/asoc.h
9451 fi
9452 fi
Sterowniki alsa
http://www.alsa-project.org/snapshot/files/
Użyłem snapshota, gdyż oficjalna wersja nie chciała współpracować z kernelem 2.6.33. (Gdzieś nawet perex się o tym wypowiadał, ale nie pamiętam gdzie.)
- alsa-driver-1.0.23.96.gda8b0.991.gd36e7.tar.bz2
Przechodzimy do katalogu /usr/src/i umieszczamy tam ściągnięty plik
cd /usr/src
cp ~/Downloads/alsa-driver-* .
bunzip2 alsa-driver-*
tar -xf alsa-driver-*
Następnie wchodzimy do nowoutworzonego katalogu
cd alsa-driver-1.0.23.96
Pora na nasz mały patch tajemny
Dowolnym edytorem tekstowym edytujemy plik alsa-kernel/pci/emu10k1/emupcm.c Ja użyję do tego vim.
vim alsa-kernel/pci/emu10k1/emupcm.c
Idziemy do linii 552 i znajdujemy następujący zapis:
static struct snd_pcm_hardware snd_emu10k1_efx_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = NUM_EFX_PLAYBACK,
.channels_max = NUM_EFX_PLAYBACK,
.buffer_bytes_max = (64*1024),
.period_bytes_min = 64,
.period_bytes_max = (64*1024),
.periods_min = 2,
.periods_max = 2,
.fifo_size = 0,
};
Zmeniamy go na następujący (poprawiamy kilka wyróżnionych linijek)
static struct snd_pcm_hardware snd_emu10k1_efx_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_S16_LE, // (Można sobie eksperymentować z SNDRV_PCM_FMTBIT_S32_LE. U mnie wyskakiwały xruny.)
.rates = SNDRV_PCM_RATE_44100,
.rate_min = 44100,
.rate_max = 44100,
.channels_min = NUM_EFX_PLAYBACK,
.channels_max = NUM_EFX_PLAYBACK,
.buffer_bytes_max = (64*1024),
.period_bytes_min = 64,
.period_bytes_max = (64*1024),
.periods_min = 2,
.periods_max = 2,
.fifo_size = 0,
};
Następnie około 1750 linii (nie wiem, czy to potrzebne, ale nie zaszkodzi):
static struct snd_pcm_hardware snd_emu10k1_fx8010_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_RESUME |
/* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 1,
.buffer_bytes_max = (128*1024),
.period_bytes_min = 1024,
.period_bytes_max = (128*1024),
.periods_min = 1,
.periods_max = 1024,
.fifo_size = 0,
};
Zamieniamy na:
static struct snd_pcm_hardware snd_emu10k1_fx8010_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_RESUME |
/* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_44100,
.rate_min = 44100,
.rate_max = 44100,
.channels_min = 1,
.channels_max = 1,
.buffer_bytes_max = (128*1024),
.period_bytes_min = 1024,
.period_bytes_max = (128*1024),
.periods_min = 1,
.periods_max = 1024,
.fifo_size = 0,
};
Ostatni drobiazg, około 1300 linii (również nie mam pojęcia do czego to służy)
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
zamieniamy na
runtime->hw.rate_min = runtime->hw.rate_max = 44100;
Pora na kompilację
wracamy do katalogu /usr/src/alsa-driver-1.0.23.96
cd /usr/src/alsa-driver-1.0.23.96
i wykonujemy kolejno:
./configure
make
make install
Restart systemu i sprawdzenie czy działa.
dmesg | grep ALSA
i dla pewności:
lsmod |grep emu
jeśli nie krzyczy, że coś mu się nie podoba — jesteśmy w domu.
Uruchamiamy jacka i cieszymy się pracą przy 44100 Hz
TODO
- Niestety na razie Multichannel Playback działa (mi) tylko z rozdzielczością 16 bitów.
- Niestety pozostał problem sterowników do Nvidia GeForce (używam dwóch monitorów).
Walka trwa zatem. Czuję, że da się zrobić więcej.