Skip to content

Commit

Permalink
Added back byte operating encoding and decoding functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
zaf committed Dec 29, 2016
1 parent 337dad8 commit 69dc1e0
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 59 deletions.
48 changes: 45 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,41 +25,83 @@ func Alaw2Ulaw(alaw []byte) []byte
```
Alaw2Ulaw performs direct A-law to u-law data conversion

#### func Alaw2UlawFrame

```go
func Alaw2UlawFrame(frame uint8) uint8
```
Alaw2UlawFrame directly converts an A-law frame to u-law

#### func DecodeAlaw

```go
func DecodeAlaw(pcm []byte) []byte
```
DecodeAlaw decodes A-law PCM data to 16bit LPCM

#### func DecodeAlawFrame

```go
func DecodeAlawFrame(frame uint8) int16
```
DecodeAlawFrame decodes an A-law PCM frame to 16bit LPCM

#### func DecodeUlaw

```go
func DecodeUlaw(pcm []byte) []byte
```
DecodeUlaw decodes u-law PCM data to 16bit LPCM

#### func DecodeUlawFrame

```go
func DecodeUlawFrame(frame uint8) int16
```
DecodeUlawFrame decodes a u-law PCM frame to 16bit LPCM

#### func EncodeAlaw

```go
func EncodeAlaw(lpcm []byte) []byte
```
EncodeAlaw encodes 16bit LPCM data to G711 A-law PCM

#### func EncodeAlawFrame

```go
func EncodeAlawFrame(frame int16) uint8
```
EncodeAlawFrame encodes a 16bit LPCM frame to G711 A-law PCM

#### func EncodeUlaw

```go
func EncodeUlaw(lpcm []byte) []byte
```
EncodeUlaw encodes 16bit LPCM data to G711 u-law PCM

#### func EncodeUlawFrame

```go
func EncodeUlawFrame(frame int16) uint8
```
EncodeUlawFrame encodes a 16bit LPCM frame to G711 u-law PCM

#### func Ulaw2Alaw

```go
func Ulaw2Alaw(ulaw []byte) []byte
```
Ulaw2Alaw performs direct u-law to A-law data conversion

#### func Ulaw2UlawFrame

```go
func Ulaw2UlawFrame(frame uint8) uint8
```
Ulaw2UlawFrame directly converts a u-law frame to A-law

#### type Decoder

```go
Expand All @@ -68,7 +110,7 @@ type Decoder struct {
```

Decoder implements an io.Reader interface. It reads G711 PCM data and decodes it
to 16bit LPCM
to 16bit 8000Hz LPCM

#### func NewAlawDecoder

Expand Down Expand Up @@ -109,8 +151,8 @@ type Encoder struct {
}
```

Encoder implements an io.Writer interface. It encodes 16bit LPCM data to G711
PCM or directly transcodes between A-law and u-law
Encoder implements an io.Writer interface. It encodes 16bit 8000Hz LPCM data to
G711 PCM or directly transcodes between A-law and u-law

#### func NewAlawEncoder

Expand Down
72 changes: 43 additions & 29 deletions alaw.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,39 +96,43 @@ func EncodeAlaw(lpcm []byte) []byte {
}
alaw := make([]byte, len(lpcm)/2)
for i, j := 0, 0; j < len(lpcm)-2; i, j = i+1, j+2 {
frame := int16(lpcm[j]) | int16(lpcm[j+1])<<8
/*
The algorithm first stores off the sign. Then the code branches.
If the absolute value of the source sample is less than 256, the 16-bit sample is simply
shifted down 4 bits and converted to an 8-bit value, thus losing the top 4 bits in the process.
However, if it is more than 256, a logarithmic algorithm is applied to the sample to
determine the precision to keep. In that case, the sample is shifted down to access the
seven most significant bits of the sample. Those seven bits are then used to determine the
precision of the bottom 4 bits (segment). Finally, the top seven bits are shifted back up four bits
to make room for the bottom 4 bits. The two are then logically OR'd together to create the
eight bit compressed sample. The sign is then applied, and the entire compressed sample
is logically XOR'd for transmission.
*/
sign := ((^frame) >> 8) & 0x80
if sign == 0 {
frame = -frame
}
if frame > alawClip {
frame = alawClip
}
var compressedByte uint8
if frame >= 256 {
segment := alawSegment[(frame>>8)&0x7F]
bottom := (frame >> (segment + 3)) & 0x0F
compressedByte = uint8(((int16(segment) << 4) | bottom))
} else {
compressedByte = uint8(frame >> 4)
}
alaw[i] = compressedByte ^ uint8(sign^0x55)
alaw[i] = EncodeAlawFrame(int16(lpcm[j]) | int16(lpcm[j+1])<<8)
}
return alaw
}

// EncodeAlawFrame encodes a 16bit LPCM frame to G711 A-law PCM
func EncodeAlawFrame(frame int16) uint8 {
/*
The algorithm first stores off the sign. Then the code branches.
If the absolute value of the source sample is less than 256, the 16-bit sample is simply
shifted down 4 bits and converted to an 8-bit value, thus losing the top 4 bits in the process.
However, if it is more than 256, a logarithmic algorithm is applied to the sample to
determine the precision to keep. In that case, the sample is shifted down to access the
seven most significant bits of the sample. Those seven bits are then used to determine the
precision of the bottom 4 bits (segment). Finally, the top seven bits are shifted back up four bits
to make room for the bottom 4 bits. The two are then logically OR'd together to create the
eight bit compressed sample. The sign is then applied, and the entire compressed sample
is logically XOR'd for transmission.
*/
sign := ((^frame) >> 8) & 0x80
if sign == 0 {
frame = -frame
}
if frame > alawClip {
frame = alawClip
}
var compressedByte uint8
if frame >= 256 {
segment := alawSegment[(frame>>8)&0x7F]
bottom := (frame >> (segment + 3)) & 0x0F
compressedByte = uint8(((int16(segment) << 4) | bottom))
} else {
compressedByte = uint8(frame >> 4)
}
return compressedByte ^ uint8(sign^0x55)
}

// DecodeAlaw decodes A-law PCM data to 16bit LPCM
func DecodeAlaw(pcm []byte) []byte {
lpcm := make([]byte, len(pcm)*2)
Expand All @@ -140,6 +144,11 @@ func DecodeAlaw(pcm []byte) []byte {
return lpcm
}

// DecodeAlawFrame decodes an A-law PCM frame to 16bit LPCM
func DecodeAlawFrame(frame uint8) int16 {
return alaw2lpcm[frame]
}

// Alaw2Ulaw performs direct A-law to u-law data conversion
func Alaw2Ulaw(alaw []byte) []byte {
ulaw := make([]byte, len(alaw))
Expand All @@ -148,3 +157,8 @@ func Alaw2Ulaw(alaw []byte) []byte {
}
return ulaw
}

// Alaw2UlawFrame directly converts an A-law frame to u-law
func Alaw2UlawFrame(frame uint8) uint8 {
return alaw2ulaw[frame]
}
10 changes: 5 additions & 5 deletions g711.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
*/

/*
Package g711 implements encoding and decoding of G711.0 compressed sound data.
G.711 is an ITU-T standard for audio companding.
Package g711 implements encoding and decoding of G711.0 compressed sound data.
G.711 is an ITU-T standard for audio companding.
For usage details please see the code snippets in the cmd folder.
For usage details please see the code snippets in the cmd folder.
*/
package g711

Expand All @@ -27,13 +27,13 @@ const (
)

// Decoder implements an io.Reader interface. It reads G711 PCM data and decodes
// it to 16bit LPCM
// it to 16bit 8000Hz LPCM
type Decoder struct {
decode func([]byte) []byte // decoding function
source io.Reader // source data
}

// Encoder implements an io.Writer interface. It encodes 16bit LPCM data to
// Encoder implements an io.Writer interface. It encodes 16bit 8000Hz LPCM data to
// G711 PCM or directly transcodes between A-law and u-law
type Encoder struct {
input int // input format
Expand Down
58 changes: 36 additions & 22 deletions ulaw.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,32 +99,36 @@ func EncodeUlaw(lpcm []byte) []byte {
}
ulaw := make([]byte, len(lpcm)/2)
for i, j := 0, 0; j < len(lpcm)-2; i, j = i+1, j+2 {
frame := int16(lpcm[j]) | int16(lpcm[j+1])<<8
/*
The algorithm first stores off the sign. It then adds in a bias value
which (due to wrapping) will cause high valued samples to lose precision.
The top five most significant bits are pulled out of the sample.
Then, the bottom three bits of the compressed byte are generated using the
segment look-up table, based on the biased value of the source sample.
The 8-bit compressed sample is then finally created by logically OR'ing together
the 5 most important bits, the 3 lower bits, and the sign when applicable. The bits
are then logically NOT'ed for transmission.
*/
sign := (frame >> 8) & 0x80
if sign != 0 {
frame = -frame
}
if frame > uLawClip {
frame = uLawClip
}
frame += uLawBias
segment := ulawSegment[(frame>>7)&0xFF]
bottom := (frame >> (segment + 3)) & 0x0F
ulaw[i] = uint8(^(sign | (int16(segment) << 4) | bottom))
ulaw[i] = EncodeUlawFrame(int16(lpcm[j]) | int16(lpcm[j+1])<<8)
}
return ulaw
}

// EncodeUlawFrame encodes a 16bit LPCM frame to G711 u-law PCM
func EncodeUlawFrame(frame int16) uint8 {
/*
The algorithm first stores off the sign. It then adds in a bias value
which (due to wrapping) will cause high valued samples to lose precision.
The top five most significant bits are pulled out of the sample.
Then, the bottom three bits of the compressed byte are generated using the
segment look-up table, based on the biased value of the source sample.
The 8-bit compressed sample is then finally created by logically OR'ing together
the 5 most important bits, the 3 lower bits, and the sign when applicable. The bits
are then logically NOT'ed for transmission.
*/
sign := (frame >> 8) & 0x80
if sign != 0 {
frame = -frame
}
if frame > uLawClip {
frame = uLawClip
}
frame += uLawBias
segment := ulawSegment[(frame>>7)&0xFF]
bottom := (frame >> (segment + 3)) & 0x0F
return uint8(^(sign | (int16(segment) << 4) | bottom))
}

// DecodeUlaw decodes u-law PCM data to 16bit LPCM
func DecodeUlaw(pcm []byte) []byte {
lpcm := make([]byte, len(pcm)*2)
Expand All @@ -136,6 +140,11 @@ func DecodeUlaw(pcm []byte) []byte {
return lpcm
}

// DecodeUlawFrame decodes a u-law PCM frame to 16bit LPCM
func DecodeUlawFrame(frame uint8) int16 {
return ulaw2lpcm[frame]
}

// Ulaw2Alaw performs direct u-law to A-law data conversion
func Ulaw2Alaw(ulaw []byte) []byte {
alaw := make([]byte, len(ulaw))
Expand All @@ -144,3 +153,8 @@ func Ulaw2Alaw(ulaw []byte) []byte {
}
return ulaw
}

// Ulaw2UlawFrame directly converts a u-law frame to A-law
func Ulaw2UlawFrame(frame uint8) uint8 {
return ulaw2alaw[frame]
}

0 comments on commit 69dc1e0

Please sign in to comment.