File src/remiaudio/codecs/g711.cr from the latest check-in


     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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
   100
   101
   102
   103
   104
   105
   106
   107
   108
   109
   110
   111
   112
   113
   114
   115
   116
   117
   118
   119
   120
   121
   122
   123
   124
   125
   126
   127
   128
   129
   130
   131
#### RemiAudio
#### Copyright (C) 2022-2024 Remilia Scarlet <remilia@posteo.jp>
####
#### This program is free software: you can redistribute it and/or modify it
#### under the terms of the GNU Affero General Public License as published by
#### the Free Software Foundation, either version 3 of the License, or (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 Affero General Public
#### License for more details.
####
#### You should have received a copy of the GNU Affero General Public License
#### along with this program.  If not, see <https://www.gnu.org/licenses/>.

module RemiAudio::Codecs
  module G117
    extend self

    RemiAudio::Codecs::G117.initLawTables()

    # :nodoc:
    LINEAR_CODE_BIAS = 0x84

    # :nodoc:
    @@muLawTable : Array(UInt8) = [] of UInt8
    @@aLawTable : Array(UInt8) = [] of UInt8

    # Converts a mu-Law sample to a signed 16-bit integer sample.
    def muLawToInt16(uval : UInt8) : Int16
      # Taken from pcm_tablegen.h in ffmpeg
      notUval : UInt8 = ~uval
      foo : Int32 = ((uval & 0xf) << 3).to_i32! + LINEAR_CODE_BIAS
      foo = foo << ((notUval & 0x70) >> 4)

      if (notUval & 0x80) != 0
        (LINEAR_CODE_BIAS - foo).to_i16!
      else
        (foo - LINEAR_CODE_BIAS).to_i16!
      end
    end

    # Converts an a-Law sample to a signed 16-bit integer sample.
    def aLawToInt16(aval : UInt8) : Int16
      # Taken from pcm_tablegen.h in ffmpeg
      seg : Int16 = 0
      aval = aval ^ 0x55
      foo : Int16 = (aval & 0xf).to_i16!
      seg = ((aval & 0x70) >> 4).to_i16!
      foo = if seg != 0
              (foo + foo + 1 + 32) << (seg + 2)
            else
              (foo + foo + 1) << 3
            end

      if (aval & 0x80) != 0
        foo
      else
        -foo
      end
    end

    # :nodoc:
    protected def makeLawTable(mask : UInt8, reverseFn : Proc(UInt8, Int16)) : Array(UInt8)
      # Taken from pcm_tablegen.h in ffmpeg
      j : Int32 = 1
      ret : Array(UInt8) = Array.new(16384, 0u8)
      ret[8192] = mask

      127u8.times do |i|
        v1 : Int32 = reverseFn.call((i ^ mask).to_u8!).to_i32!
        v2 : Int32 = reverseFn.call(((i + 1) ^ mask).to_u8!).to_i32!
        v  : Int32 = (v1 + v2 + 4) >> 3

        while j < v
          ret[8192 - j] = i ^ (mask ^ 0x80)
          ret[8192 + j] = i ^ mask
          j += 1
        end
      end

      while j < 8192
        ret[8192 - j] = 127u8 ^ (mask ^ 0x80)
        ret[8192 + j] = 127u8 ^ mask
        j += 1
      end

      ret[0] = ret[1]
      ret
    end

    # :nodoc:
    def self.initLawTables
      @@muLawTable = makeLawTable(0xff, ->muLawToInt16(UInt8))
      @@aLawTable = makeLawTable(0xd5, ->aLawToInt16(UInt8))
    end

    # Converts a 16-bit signed integer sample into a mu-Law sample.
    @[AlwaysInline]
    def int16ToMuLaw(sample : Int16) : UInt8
      @@muLawTable[(sample.to_i32! + 32768) >> 2]
    end

    # Converts an array of 16-bit signed integer samples into an array of mu-Law samples.
    def int16ToMuLaw(samples : Array(Int16)) : Array(UInt8)
      samples.map { |smp| int16ToMuLaw(smp) }
    end

    # Converts a 16-bit signed integer sample into a a-Law sample.
    @[AlwaysInline]
    def int16ToALaw(sample : Int16) : UInt8
      @@aLawTable[(sample.to_i32! + 32768) >> 2]
    end

    # Converts an array of 16-bit signed integer samples into an array of a-Law samples.
    def int16ToMuLaw(samples : Array(Int16)) : Array(UInt8)
      samples.map { |smp| int16ToALaw(smp) }
    end

    # Converts an array of mu-Law samples into an array of 16-bit signed integer samples.
    def muLawToInt16(samples : Array(Int16)) : Array(UInt8)
      samples.map { |smp| muLawToInt16(smp) }
    end

    # Converts an array of ma-Law samples into an array of 16-bit signed integer samples.
    def aLawToInt16(samples : Array(Int16)) : Array(UInt8)
      samples.map { |smp| aLawToInt16(smp) }
    end
  end
end