Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

17.10.2008, 14:55

Knacken nach runtersamplen von 48kHz PCM auf 8kHz

Hi an alle,

ich zeichne Sprache vom Mikrofon mit DirectSound in einem RingBuffer auf.
Und zwar mit 48kHz 16bit PCM.
Dabei fange ich alle 20ms aufgezeichnetes ab.
Dieses 20ms Sample nehme ich nun und sample es auf 8kHz runter.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int CAudioOut::Reduce48to8kHz(short* pBuffer, int nBytesToReduce) 
{ 
    ASSERT((nBytesToReduce % 6) == 0); 
    short* pSrc = pBuffer; 
    short* pDst = pBuffer; 
    for(int i = 0; i < (nBytesToReduce / 6); i++) 
    { 
        long val = 0; 
        val = *pSrc++; 
        val += (long)*pSrc++ * 4; 
        val += (long)*pSrc++ * 14; 
        val += (long)*pSrc++ * 14; 
        val += (long)*pSrc++ *4; 
        val += *pSrc++; 
        *pDst++ = (short)(val/38); 
    } 
    return (pDst - pBuffer); 
}


pBuffer sind die Rohdaten des Samples. nBytesToReduce in diesem Fall 960byte.

Dann gehe ich hin und encodiere dies mit ulaw und zwar folgendermaßen.

C-/C++-Quelltext

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
static short seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF, 
                0x3FF, 0x7FF, 0xFFF, 0x1FFF}; 

static int search(    int val,    short *table, int size) 
{ 
    int i; 
    for (i = 0; i < size; i++) 
    { 
    if (val <= *table++) 
            return (i); 
    } 
    return (size); 
} 

unsigned char CG711::encodeULaw(short pcm_val) 
{ 

    static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 
                             4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 
                             5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 
                             5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 
                             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
                             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
                             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
                             6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 
                             7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; 
    int sign, exponent, mantissa; 
    unsigned char ulawbyte; 

    // Get the sample into sign-magnitude. */ 

    sign = (pcm_val >> 8) & 0x80;        // set aside the sign */ 

    if (sign != 0) pcm_val = -pcm_val;        // get magnitude */ 

    if (pcm_val > CLIP) pcm_val = CLIP;        // clip the magnitude */ 


    // Convert from 16 bit linear to ulaw. */ 

    pcm_val = pcm_val + BIAS; 
    exponent = exp_lut[(pcm_val >> 7) & 0xFF]; 
    mantissa = (pcm_val >> (exponent + 3)) & 0x0F; 
    ulawbyte = ~(sign | (exponent << 4) | mantissa); 
    #ifdef ZEROTRAP 
      if (ulawbyte == 0) ulawbyte = 0x02;    // optional CCITT trap */ 

    #endif 

    return(ulawbyte); 
} 

//Diese Methode rufe ich aus meiner Funktion folgendermaßen auf. 

for(int i = 0; i < size2; i++) 
        newPacket.m_payload[i] = g711.encodeULaw(downsampledAudio[i]); 
//downsampledAudio ist mein vorher reduzierter Buffer


Nach dem ich dies nun alles ausgeführt habe und das Packet versende kommt auf der anderen Seite(IP Phone) zwar etwas verständliches raus, das Ergebnis ist aber nur befriedigend, da immer noch regelmäßig ein störendes Knacken auftritt.

Ich weiß nicht mehr warum dies so ist. Vllt. sieht ja jemand von euch wo mein Fehler liegt.

Gruß

CrazyPlaya
Arbeitswut ist eine psychische Störung, die schon mit einer Tasse Kaffee und einem netten Gespräch geheilt werden kann

xardias

Community-Fossil

Beiträge: 2 731

Wohnort: Santa Clara, CA

Beruf: Software Engineer

  • Private Nachricht senden

2

17.10.2008, 18:47

Ich kenne den Algorithmus den du verwendest nicht. Doch solltest du bedenken, dass die Störanfälligkeit mit der Komprimierung bzw dem Downsamplen stark ansteigt. Da ist es sehr wichtig Kodierungen zu verwenden die Fehlerkorrekturen zulassen.

Zur Fehlersuche würde ich dir raten die Daten direkt auf dem Rechner zu dekodieren und wieder abzuspielen. So wie es jetzt ist sind da zu viele Unbekannte als dass man da was zu sagen könnte..