LINUX.ORG.RU

Проброс JACK в ALSA

 , asound, , libasound


0

1

Здравствуйте! В целях экспериментов с коммутацией, — решил написать велосипед утилиту, которая бы пробрасывала JACK в ALSA, решил пойти от обратного, не ALSA в JACK, а наоборот, потому как plug-выходы с джеком хотят подхватывать далеко не все приложения. В общем-то затея почти получилась, но застопорился на одном месте, перерыв интернеты, не понял как решить. В общем у меня идёт звук с первого JACK входа в альсу, но звучит это словно — дико перегружено, с жутким шумом, но как-никак, а что-то слышно, уже какой-то прогресс.

Весь код: http://pastebin.com/xBZjxd4H Makefile: http://pastebin.com/paQaxgfp

Инициализация альсы:

    snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
    snd_pcm_set_params( playback_handle, SND_PCM_FORMAT_S32_LE,
                              SND_PCM_ACCESS_RW_INTERLEAVED,
                              1/*channels*/, sample_rate/*get_from_jack*/, 1, 5000000);

Вот процессинг джека:

int jack_process(jack_nframes_t nframes, void *arg) {
    jack_default_audio_sample_t *in_l;
 
    in_l = (jack_default_audio_sample_t *)
        jack_port_get_buffer(input_port_left, nframes);

    snd_pcm_writei(playback_handle, in_l, nframes);
 
    return 0;
}
in_l — это по сути массив float-ов в пределах -1/+1, а то и меньше диапазон.

Звук в альсу идёт, но с дикими шумами и перегрузами. Что делаю не так? Спасибо.

P.S. Ещё по возможности объясните как быть с snd_pcm_writei, когда нужно стерео.



Последнее исправление: unclechu (всего исправлений: 1)

И те 5% что остались)

snd_pcm_writei(playback_handle, in_l, nframes);

in_l вроде бы должно быть целое число.

xSudo ★★★
()
Ответ на: комментарий от lazyklimm

Firefox (HTML5), Skype, гуглоплагин для hangouts, множество игр из Steam, могу ещё перечислить.

Но вопрос по топику не в том как настроить проброс альсы в джек, а конкретно по работе с libasound, веточка как-никак «development».

unclechu
() автор топика
Ответ на: комментарий от xSudo

Вариант с in_l как целое — отбрасывается, там передаётся буфер, и, как уже говорил, звук я слышу, только он словно пропущен через фузз, как бы ход мысли верный, но фаза по всей видимости строится другим диапазоном чисел, нежели чем у JACK.

unclechu
() автор топика
Ответ на: комментарий от xSudo

По ALSA_BIT_DEPTH: Из возможных вариантов SND_PCM_FORMAT_* работает делко не всё. Прбовал и S8 и S16 и ещё какие-то, везде одно и тоже.

О перегрузе так же говорит, что звук мягко говоря ощутимо громче, чем тот же трек напрямую в альсу из плеера. Пробовал смещать диапазон, но по большей части без успешно, что-то в корне делается не так. Полагаю, его нужно как-то попросту сузить, потому как по всей видимости по фазе получается слишком большая амплитута колебаний, из-за чего собственно такая громкость и эпичный фузз. С математикой у меня туго, как сузить диапазон? И тут надо в какой-то конкретной же пропорции его сужать, а не от фонаря... Хм...

unclechu
() автор топика
Ответ на: комментарий от unclechu

звук я слышу, только он словно пропущен через фузз

запили синусоиду/меандр и посмотри на форму результирующей волны, возможно прояснит картину

lazyklimm ★★★★★
()
Ответ на: комментарий от lazyklimm

Понимаю, что если долго тыкаться, можно чего-нибудь добиться, но для меня интересно именно реализовать задуманное, даже если УМтожеВзаР. Иногда лишний раз неудобно дёргать .asoundrc, просто нужно что-то поделать с JACK-ом, а закрывать все открытые приложения и прочее, банально воспользоваться тюнером guitarix-а по-быстрому. А JACK включен не всегда. В общем оффтопик.

unclechu
() автор топика
Ответ на: комментарий от lazyklimm

С волной-то всё будет в порядке, там float, который будет в порядке в пределах jack-а, но вот у альсы какой-то более узкий диапазон, нежели у джека, и уже в альсе (на выходе) получается дикий square.

UPD: Если отправлю всё это на какой-нибудь другой порт джека, — то всё ок.

unclechu
() автор топика
Последнее исправление: unclechu (всего исправлений: 2)
Ответ на: комментарий от unclechu

как сузить диапазон?

в первом приближении - умножать значение сэмпла, не?

И тут надо в какой-то конкретной же пропорции его сужать, а не от фонаря...

подбери методом тыка пропорцию, а там авось и придумается, что за число

lazyklimm ★★★★★
()

Подскажите, есть тут математики? Как сузить диапазон? Вот есть число в пределах -0.1 и +0.1, нужно преобразовать это число, как если бы оно было в пределах -0.01 и 0.

unclechu
() автор топика
Ответ на: комментарий от xSudo

Как сузить диапазон решил методом математического тыка:

#!/usr/bin/env python

src = 0.123
r1 = (-1, +1)
r2 = (0.5, 0)

r1r = r1[1] - r1[0]
if r1r < 0: r1r = -r1r

r2r = r2[1] - r2[0]
if r2r < 0: r2r = -r2r

target = (src * r2r) / r1r
if r1[0] != r2[0]: target -= (r1[0] - r2[0]) + 1

print target
Сейчас попробую посужать амплитуду.

unclechu
() автор топика
Последнее исправление: unclechu (всего исправлений: 2)
Ответ на: комментарий от unclechu

Нет, алгоритм ещё косячный, надо править.

unclechu
() автор топика
Ответ на: комментарий от xSudo

Ничего не понимаю, на изменение амплитуды оно вообще не реагирует. Что-то тут не то. Может быть ваша идея с целым имеет смысл?

    for (i=0; i<nframes; i++) {
        in_l[i] = in_l[i] * 200000000;
    }
Слышно тоже самое. Амплитуда увеличена в 20 миллионов раз.

unclechu
() автор топика
Ответ на: комментарий от xSudo

Не понял что конкретно тут происходит, но задачу решил! Наткнулся в отчаянном сёрфинге на: http://stackoverflow.com/questions/2180909/how-to-use-alsas-snd-pcm-writei и далее по ссылке: http://pastebin.com/m2f28b578

Итого:

#define ALSA_BIT_DEPTH SND_PCM_FORMAT_S16

double fclip(double value, double start, double end) {
    return 0.5 * ( fabs(value-start) + (start+end) - fabs(value-end) );
}
    static short *buffer = NULL;
    if (buffer == NULL) {
        buffer = malloc(nframes * sizeof(float));
    }

    for (i=0; i<nframes; i++) {
        buffer[i] = (short)fclip( 32767.0 * in_l[i], -32767, +32768 );
    }

    err = snd_pcm_writei(playback_handle, buffer, nframes);
И оно поёт! Как и ожидается! С целочисленным вы были правы, просто изначально неправильно вас понял.

Осталось разобраться со стерео.

unclechu
() автор топика
Ответ на: комментарий от unclechu

Отлично)

А со стерео, думаю стоит попробовать, что-то вроде такого.

for (i=0; i<nframes; i++) {
    buffer[2*i] = (short)fclip( 32767.0 * in_l[i], -32767, +32768 );
    buffer[2*i+1] = (short)fclip( 32767.0 * in_r[i], -32767, +32768 );
    }

err = snd_pcm_writei(playback_handle, buffer, 2*nframes);

Хотя я конечно не уверен. Суть в том, чтобы загнать в буфер оба канала через бит.

xSudo ★★★
()
Ответ на: комментарий от xSudo

Катит! Извиняюсь. Я затупил, теперь всё работает, осталось дело за деталями косметикой.

Вот решение:

    int res;
    int i, n;

    for (i=0, n=0; i<nframes*2; i=i+2, n++) {
        buffer16bit[i] = (short)alsa_phase(in_l[n]);
        buffer16bit[i+1] = (short)alsa_phase(in_r[n]);
    }

    res = snd_pcm_writei(playback_handle, buffer16bit, nframes);
    if (res == -EPIPE) {
        res = snd_pcm_recover(playback_handle, res, 1);
        if (res >= 0)
            res = snd_pcm_writei(playback_handle, buffer16bit, nframes);
    }

unclechu
() автор топика
Ответ на: комментарий от lazyklimm

а конкретно? УМВР

VirtualBox тот же, правда он прекрасно работает с PulseAudio поверх jack.

m0rph ★★★★★
()
Ответ на: комментарий от xSudo

Только доведу до товарного вида — будет!

unclechu
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.