RSS
 

Jak to e-​mu1820m do współpracy z Linuksem namawiałem

26 lis

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/​w​i​k​i​/​w​i​k​k​a​.​p​h​p​?​w​a​k​k​a​=​e​m​u​&​a​m​p​;​s​h​o​w​_​c​o​m​m​e​nts=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.3329-realtime_2.6.3329.1_i386.deb (27.5 MiB)
  • linux-headers-2.6.33-29_2.6.3329.1_all.deb (9.6 MiB)
  • linux-headers-2.6.3329-realtime_2.6.3329.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.3329-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/​s​n​a​p​s​h​o​t​/​f​iles/

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

  1. Niestety na razie Multichannel Playback działa (mi) tylko z rozdzielczością 16 bitów.
  2. Niestety pozostał problem sterowników do Nvidia GeForce (używam dwóch monitorów).

Walka trwa zatem. Czuję, że da się zrobić więcej.