alaw.cpp 3.32 KB
Newer Older
jpbl's avatar
jpbl committed
1
2
3
4
5
6
7
/**
 *  Copyright (C) 2004-2005 Savoir-Faire Linux inc.
 *  Author:  Yan Morin <yan.morin@savoirfairelinux.com>
 *  Author:  Laurielle Lea <laurielle.lea@savoirfairelinux.com>
 *                                                                              
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 3 of the License, or
jpbl's avatar
jpbl committed
9
10
11
12
13
14
15
16
17
18
19
20
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *                                                                              
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

21
22
23
24
25
#include "common.h"
#include "audiocodec.h"

class Alaw : public AudioCodec {
public:
26
27
28
29
30
31
32
33
    // 8 PCMA A 8000 1 [RFC3551]
   	Alaw(int payload=0)
 	: AudioCodec(payload, "PCMA")
	{
  		_clockRate = 8000;
  		_channel   = 1;
	}

Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
34
        virtual ~Alaw(){}
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	virtual int codecDecode (short *dst, unsigned char *src, unsigned int size) 
	{
		int16* end = dst+size;
        	while(dst<end)
                	*dst++ = ALawDecode(*src++);
        	return size<<1;
	}

	virtual int codecEncode (unsigned char *dst, short *src, unsigned int size) 
	{	
		size >>= 1;
        	uint8* end = dst+size;
        	while(dst<end)
                	*dst++ = ALawEncode(*src++);
        	return size;
	}



	int ALawDecode(uint8 alaw)
	{
		alaw ^= 0x55;  // A-law has alternate bits inverted for transmission
        	uint sign = alaw&0x80;
        	int linear = alaw&0x1f;
        	linear <<= 4;
		linear += 8;  // Add a 'half' bit (0x08) to place PCM value in middle of range

        	alaw &= 0x7f;
        	if(alaw>=0x20)
        	{
        		linear |= 0x100;  // Put in MSB
			uint shift = (alaw>>4)-1;
                	linear <<= shift;
        	}

       	 	if(!sign)
                	return -linear;
        	else
                	return linear;
	}


	uint8 ALawEncode (int16 pcm16)
	{
		int p = pcm16;
        	uint a;  // u-law value we are forming

        	if(p<0)
        	{
			p = ~p;
			 a = 0x00; // sign = 0
		}
		else
		{
			//+ve value
			a = 0x80; //sign = 1
		}
		//calculate segment and interval numbers
		 p >>= 4;
        	if(p>=0x20)
95
                {
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
                	if(p>=0x100)
                        {
                        	p >>= 4;
                        	a += 0x40;
                        }
                	if(p>=0x40)
                        {
                        	p >>= 2;
                        	a += 0x20;
                        }
                	if(p>=0x20)
                        {
                        	p >>= 1;
                        	a += 0x10;
                        }
111
                }
112
113
114
115
116
	// a&0x70 now holds segment value and 'p' the interval number
	a += p; // a now equal to encoded A-law value

	return a^0x55; // A-law has alternate bits inverted for transmission
	}
117
118
119
120

};

// the class factories
121
extern "C" AudioCodec* create() {
122
    return new Alaw(8);
123
124
}

125
extern "C" void destroy(AudioCodec* a) {
126
    delete a;
jpbl's avatar
jpbl committed
127
128
}