1. from bitstring import BitArray, BitStream
  2.  
  3. # convert amr payload to storage format
  4. # according RFC 4867
  5. # http://tools.ietf.org/html/rfc4867
  6. # see http://packages.python.org/bitstring/walkthrough.html
  7. #
  8. # RFC 4867 (Bandwidth-Efficient Mode) p22...
  9. #   In the payload, no specific mode is requested (CMR=15), the speech
  10. #   frame is not damaged at the IP origin (Q=1), and the coding mode is
  11. #   AMR 7.4 kbps (FT=4).  The encoded speech bits, d(0) to d(147), are
  12. #   arranged in descending sensitivity order according to [2].  Finally,
  13. #   two padding bits (P) are added to the end as padding to make the
  14. #   payload octet aligned.
  15. #    0                   1                   2                   3
  16. #    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  17. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  18. #   | CMR=15|0| FT=4  |1|d(0)                                       |
  19. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  20. #   |                                                               |
  21. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  22. #   |                                                               |
  23. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  24. #   |                                                               |
  25. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  26. #   |                                                     d(147)|P|P|
  27. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  28. #
  29. # RFC 4867 Section 5.3 (AMR and AMR-WB Storage Format)
  30. #   The following example shows an AMR frame in 5.9 kbps coding mode
  31. #   (with 118 speech bits) in the storage format.
  32. #    0                   1                   2                   3
  33. #    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  34. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  35. #   |P| FT=2  |Q|P|P|                                               |
  36. #   +-+-+-+-+-+-+-+-+                                               +
  37. #   |                                                               |
  38. #   +          Speech bits for frame-block n, channel k             +
  39. #   |                                                               |
  40. #   +                                                           +-+-+
  41. #   |                                                           |P|P|
  42. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
  43. #
  44. def amrPayload2Storage_EfficientMode(payload):
  45.     bitlen = [95,103,118,134,148,159,204,244,39]
  46.     amr = BitArray(bytes=payload)
  47.     cmr = amr[0:4]
  48.     mode = amr[5:9]
  49.     assert mode.uint >=0 and mode.uint <=8
  50.     qual = amr[9:10]
  51.     voice = amr[10:10+bitlen[mode.uint]]
  52.     #print("cmr=%d\tmod=%d\tqual=%d\tvoicebits=%d" % (cmr.uint,mode.uint,qual.uint,voice.len))
  53.     storage = BitArray(bin='0')
  54.     storage.append(mode)
  55.     storage.append(qual)
  56.     storage.append('0b00') # padding
  57.     assert storage.len==8,"check length of storage header is one byte"
  58.     storage.append(voice)
  59.     return storage.tobytes()
  60.  
  61. #4.4.5.1.  Basic Single-Channel Payload Carrying Multiple Frames
  62. #
  63. #   The following diagram shows an octet aligned payload from a single
  64. #   channel payload type that carries two AMR frames of 7.95 kbps coding
  65. #   mode (FT=5).  In the payload, a codec mode request is sent (CMR=6),
  66. #   requesting the encoder at the receiver's side to use AMR 10.2 kbps
  67. #   coding mode.  No frame CRC, interleaving, or robust sorting is in
  68. #   use.
  69. #
  70. #    0                   1                   2                   3
  71. #    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  72. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  73. #   | CMR=6 |R|R|R|R|1|FT#1=5 |Q|P|P|0|FT#2=5 |Q|P|P|   f1(0..7)    |
  74. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  75. #   |   f1(8..15)   |  f1(16..23)   |  ....                         |
  76. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  77. #   : ...                                                           :
  78. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  79. #   |                         ...   |f1(152..158) |P|   f2(0..7)    |
  80. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  81. #   |   f2(8..15)   |  f2(16..23)   |  ....                         |
  82. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  83. #   : ...                                                           :
  84. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  85. #   |                         ...   |f2(152..158) |P|
  86. #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  87. #
  88. def amrPayload2Storage_OctetAlignedMode(payload):
  89.     try:
  90.         # assume no interleaving, CRCs or bit re-ordering
  91.         bitlen = [95,103,118,134,148,159,204,244,39]
  92.         amr = BitArray(bytes=payload)
  93.         cmr = amr[0:4]
  94.         res = amr[4:8]
  95.         assert res.uint==0,'amr[4:8] must be zero'
  96.         f = amr[8]
  97.         mode = amr[9:13]
  98.         qual = amr[13:14]
  99.         pad = amr[14:16]
  100.         if mode.uint >=0 and mode.uint <= 8:
  101.             assert amr.len >= 16+bitlen[mode.uint]
  102.             voice = amr[16:16+bitlen[mode.uint]]
  103.             storage = BitArray(bin='0')
  104.             storage.append(mode)
  105.             storage.append(qual)
  106.             storage.append('0b00') # padding
  107.             assert storage.len==8,"check length of storage header is one byte"
  108.             storage.append(voice)
  109.             return storage.tobytes()
  110.     except:
  111.         pdb.set_trace()
  112.     return ''