powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / 4-bit IMA ADPCM 8000 Hz <> 8-bit signed linear PCM 8000 Hz написать реально?
4 сообщений из 4, страница 1 из 1
4-bit IMA ADPCM 8000 Hz <> 8-bit signed linear PCM 8000 Hz написать реально?
    #38923241
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не люблю нерешенных вопросов, 17447907

Сдается мне, что Unimodem драйвер на Виста- 8.1 будет нормально работает только с ADPCM -форматами.
Ну т.е. нужно имплементировать:
Код: plaintext
1.
HKR, WaveDriver,    XformID       , 1,  04, 00 //4-bit IMA ADPCM 8000 Hz format.


По крайней мере с XformID=04 есть стабильный звук в обе стороны -естественно на данный момент это шум, за отсутствием кодера-декодера.

Ну возьмем к примеру PlayBack. Т.е. задача декодирования ADPCM 4 bit -> PCM 16 bit

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
       case stSend:
          {
            int lendone = dleData.PutDleData(pBuf, len);

            if (lendone > 0) {
                PTRACE(4, "--> DLE " << lendone << " bytes");

                len -= lendone;
                pBuf += lendone;
            }

            int dt = dataType;
            BYTE Buf[1024];

            for(;;) {
              int count = dleData.GetData(Buf, sizeof(Buf)); //< здесь предполагаются данные 4-bit IMA ADPCM 8000 Hz
              PTRACE(4, "Count: " << count << " bytes");
...
            if (нужно преобразование формата) {
               if (8bit -> 16bit) {  //(для примера)
                const signed char *pb = (const signed char *)Buf;
                PInt16 Buf2[sizeof(Buf)];
                PInt16 *ps = Buf2;
...
                            // калькуляция зависит от 8-битного формата на входе (это все сделано)
                            while (count--)
                              *ps++ = (PInt16)8bit2linear(*pb++); //из 1 байта делаем 2 байта,
                            break;
...
                        count = int(pb - (const signed char *)Buf);

                        currentClassEngine->Send(Buf2, count*sizeof(*ps));
              }else  if (4bit -> 16bit) {  //то что хочется сделать, т.е. ADPCM 4 bit -> PCM 16 bit
                   //ну полагаю из N byte ADPCM надо сделать 4 * N byte PCM, но уже хитрым способом, судя по дебагу N(как правило)=32
                   currentClassEngine->Send(BufPCX16, countPCX16);
                
              } else { //16bit -> 16bit без декодирования, это сделал
                  currentClassEngine->Send(Buf, count);
              }
          }



Дебаг показывает, что код скидывает грубо по 32 байта за раз (т.е. это будет 32 байта 4-битного ADPCM)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
2015/04/01 00:18:18.946	          (e):1d7c	--> DLE 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 0 bytes
2015/04/01 00:18:18.946	          (e):1d7c	--> DLE 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 31 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 0 bytes
2015/04/01 00:18:18.946	          (e):1d7c	--> DLE 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 0 bytes
2015/04/01 00:18:18.946	          (e):1d7c	--> DLE 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 31 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 0 bytes
2015/04/01 00:18:18.946	          (e):1d7c	--> DLE 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 32 bytes
2015/04/01 00:18:18.946	          (e):1d7c	Count: 0 bytes




1) Есть ли какие хорошие примеры? Ну я чуть пошерстил google, в spandsp вроде есть, не уверен что именно то что нужно.
Причем надо чтобы код можно было "воткнуть" в приведенный контекст.
2) Данные конвертируются динамически блоками. Достаточен ли кусок длиной в 32 байта 4-битного ADPCM (см.выше) для конвертации его (этого куска) в 16-битный PCM? Потому что если не достаточно и надо брать больший кусок, то код еще усложняется.

Ну, обратное кодирование пока не рассматриваю, хоть в одну сторону сперва б сделать.
...
Рейтинг: 0 / 0
4-bit IMA ADPCM 8000 Hz <> 8-bit signed linear PCM 8000 Hz написать реально?
    #38923286
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Опс,
похоже далеко ходить не надо, там уже почти все подогнано под "copy-paste":

http://sourceforge.net/p/opalvoip/code/HEAD/tree/opal/tags/v3_14_3/plugins/audio/IMA_ADPCM/ima_adpcm.c

Код: plaintext
1.
static void adpcm_decoder(char indata[], short outdata[], int len)



С кодером чуть посложнее.

Код: plaintext
1.
static void adpcm_coder(short indata[], char outdata[], int len, struct adpcm_state *state)



По идее этот плагин независимо компилируется и подсасывается приложением (если dll лежит в папке с exe и с opal.dll, а opal там лежит ибо приложение на нем базируется). Но непонятно как этим воспользоваться именно для конвертирования формата голосовых данных модема.
Поэтому проще выдрать код из плагина и бухнуть в exe-шник.
(при использовании кодека в VOIP достаточно положить плагин и тупо указать кодек).
...
Рейтинг: 0 / 0
4-bit IMA ADPCM 8000 Hz <> 8-bit signed linear PCM 8000 Hz написать реально?
    #38924367
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чет не получается у меня декодировать ADPCM->PCM.
Пробую
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
       case stSend:
          {
            int lendone = dleData.PutDleData(pBuf, len);

            if (lendone > 0) {
                PTRACE(4, "--> DLE " << lendone << " bytes");

                len -= lendone;
                pBuf += lendone;
            }

            int dt = dataType;
            BYTE Buf[1024];

            for(;;) {
              int count = dleData.GetData(Buf, sizeof(Buf));

...  
 
                        short Buf2[sizeof(Buf)*2-2];
                        adpcm_decoder((char *)Buf, (short *)Buf2 ,count);
                        currentClassEngine->Send(Buf2, count*2-2);


Код adpcm_decoder взял из ссылки выше.
http://sourceforge.net/p/opalvoip/code/HEAD/tree/opal/tags/v3_14_3/plugins/audio/IMA_ADPCM/ima_adpcm.c

Код: plaintext
1.
static void adpcm_decoder(char indata[], short outdata[], int len)


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
static void adpcm_decoder(char indata[], short outdata[], int len)
{
    signed char *inp;           /* Input buffer pointer */
    short *outp;                /* output buffer pointer */
    int sign;                   /* Current adpcm sign bit */
    int delta;                  /* Current adpcm output value */
    int step;                   /* Stepsize */
    int valpred;                /* Predicted value */
    int vpdiff;                 /* Current change to valpred */
    int index;                  /* Current step change index */
    int inputbuffer = 0;        /* place to keep next 4-bit value */
    int bufferstep;             /* toggle between inputbuffer/input */

    outp = outdata;
    inp = (signed char *)indata;

    valpred = 0;
    index = 0;
    memcpy((char *)&valpred, (char *)inp, 2);
    inp += 2; //skip first 16 bits sample
    index = (int)(unsigned char)*inp;
    inp += 2; //skip index

    step = stepsizeTable[index];
    len -= 4; //skip header

    bufferstep = 0;

    len *= 2;

    for ( ; len > 0 ; len-- ) {
        /* Step 1 - get the delta value */
        if ( bufferstep ) {
            delta = inputbuffer & 0xf;
        } else {
            inputbuffer = *inp++;
            delta = (inputbuffer >> 4) & 0xf;
        }
        bufferstep = !bufferstep;

        /* Step 2 - Find new index value (for later) */
        index += indexTable[delta];
        if ( index < 0 ) index = 0;
        if ( index > 88 ) index = 88;

        /* Step 3 - Separate sign and magnitude */
        sign = delta & 8;
        delta = delta & 7;
        /* Step 4 - Compute difference and new predicted value */
        /*
        ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
        ** in adpcm_coder.
        */
        vpdiff = step >> 3;
        if ( delta & 4 ) vpdiff += step;
        if ( delta & 2 ) vpdiff += step>>1;
        if ( delta & 1 ) vpdiff += step>>2;

        if ( sign )
          valpred -= vpdiff;
        else
          valpred += vpdiff;

        /* Step 5 - clamp output value */
        if ( valpred > 32767 )
          valpred = 32767;
        else if ( valpred < -32768 )
          valpred = -32768;

        /* Step 6 - Update step value */
        step = stepsizeTable[index];

        /* Step 7 - Output value */
        *outp++ = (char)valpred;
    }
}



слышу шум.

Модем скидывает всегда по 32 байта.
Так понимаю на входе Buf с эффективной длиной 32, на выходе байтов грубо в 4 раза больше, т.е к-во shot в 2 раза больше.

Что не так делаю? Возникает правда сомнение, правильную ли величину я засовываю в int len, но я так понимаю вот вам кусок длиной len, лежит в Buf, надо переложить в Buf2.
...
Рейтинг: 0 / 0
4-bit IMA ADPCM 8000 Hz <> 8-bit signed linear PCM 8000 Hz написать реально?
    #38927382
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопрос снимаю.
Мне удалось вылечить Unimodem драйвер на Vista-8.1.
Теперь стандартные 8-битные форматы нормально работают и на PlayBack и на Recording.
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / 4-bit IMA ADPCM 8000 Hz <> 8-bit signed linear PCM 8000 Hz написать реально?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]