File: SampleTransform.py

package info (click to toggle)
libinstpatch 1.1.7-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,384 kB
  • sloc: ansic: 50,922; python: 429; xml: 130; makefile: 10
file content (171 lines) | stat: -rwxr-xr-x 5,864 bytes parent folder | download | duplicates (2)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#!/usr/bin/python
#
# Project: lib Instrument Patch Python testing suite
# File:    SF2.py
# Descr:   SoundFont tests
# Author:  Element Green <element@elementsofsound.org>
# Date:    2016-07-01
# License: Public Domain
#
"""
Convert between all possible audio format pairs using the following steps:
- Convert double to first format of format pair
- Convert from first format to second format
- Convert second format back to double
- Calculate maximum audio sample difference between new double audio and original
"""

import Test
import gi
import ctypes
import math
import sys

from gi.repository import GObject

gi.require_version ('Ipatch', '1.1')
from gi.repository import Ipatch

# Default values are non powers of 2 to decrease the chance of masking periodic data issues
DEFAULT_SAMPLE_SIZE             = 1756          # default test waveform size in samples
DEFAULT_SAMPLE_PERIOD           = 123           # default waveform period in samples
DEFAULT_TRANSFORM_SIZE          = 65000         # default transform buffer size in bytes
MAX_DIFF_ALLOWED                = 0.016         # maximum difference allowed

# all available sample format combinations
testFormats = (
  Ipatch.SampleWidth.BIT8,
  Ipatch.SampleWidth.BIT16,
  Ipatch.SampleWidth.BIT24,
  Ipatch.SampleWidth.BIT32,
  Ipatch.SampleWidth.FLOAT,
  Ipatch.SampleWidth.DOUBLE,
  Ipatch.SampleWidth.REAL24BIT,

  Ipatch.SampleWidth.BIT8 | Ipatch.SampleSign.UNSIGNED,
  Ipatch.SampleWidth.BIT16 | Ipatch.SampleSign.UNSIGNED,
  Ipatch.SampleWidth.BIT24 | Ipatch.SampleSign.UNSIGNED,
  Ipatch.SampleWidth.BIT32 | Ipatch.SampleSign.UNSIGNED,
  Ipatch.SampleWidth.REAL24BIT | Ipatch.SampleSign.UNSIGNED,

  Ipatch.SampleWidth.BIT16 | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.BIT24 | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.BIT32 | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.FLOAT | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.DOUBLE | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.REAL24BIT | Ipatch.SampleEndian.BENDIAN,

  Ipatch.SampleWidth.BIT16 | Ipatch.SampleSign.UNSIGNED | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.BIT24 | Ipatch.SampleSign.UNSIGNED | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.BIT32 | Ipatch.SampleSign.UNSIGNED | Ipatch.SampleEndian.BENDIAN,
  Ipatch.SampleWidth.REAL24BIT | Ipatch.SampleSign.UNSIGNED | Ipatch.SampleEndian.BENDIAN
)

testFormatNames = (
  "8bit-signed",
  "16bit-signed-lendian",
  "24bit-signed-lendian",
  "32bit-signed-lendian",
  "float-lendian",
  "double-lendian",
  "real24bit-signed-lendian",

  "8bit-unsigned",
  "16bit-unsigned-lendian",
  "24bit-unsigned-lendian",
  "32bit-unsigned-lendian",
  "real24bit-unsigned-lendian",

  "16bit-signed-bendian",
  "24bit-signed-bendian",
  "32bit-signed-bendian",
  "float-bendian",
  "double-bendian",
  "real24bit-signed-bendian",

  "16bit-unsigned-bendian",
  "24bit-unsigned-bendian",
  "32bit-unsigned-bendian",
  "real24bit-unsigned-bendian"
)


parser = Test.createArgParser ('libInstPatch audio sample transform tests')
parser.add_argument ( '-s', '--size', type=int, default=DEFAULT_SAMPLE_SIZE, help='Size of audio to transform in frames')
parser.add_argument ('-p', '--period', type=int, default=DEFAULT_SAMPLE_PERIOD, help='Period size in frames')
parser.add_argument ('-t', '--trans', type=int, default=DEFAULT_TRANSFORM_SIZE, help='Transform size in bytes')
args = Test.parseArgs (parser)

Ipatch.init ()

# Determine host endian byte order
hostEndian = Ipatch.SampleEndian.BENDIAN if sys.byteorder == 'big' else Ipatch.SampleEndian.LENDIAN

# Create double floating point sample data audio
sampleSize = args.size
period = args.period
sampleDataArray = (ctypes.c_double * sampleSize)()

for pos in xrange (0, sampleSize):
  periodPos = math.fmod (pos, period) / period
  sampleDataArray[pos] = math.sin (periodPos * 2 * math.pi)

sampleData = bytearray (sampleDataArray)

# Create sample transform object and initialize size
trans = Ipatch.SampleTransform ()
trans.alloc_size (args.trans)

failcount = 0
max_maxdiff = 0.0

for isrc in xrange (0, len (testFormats)):
  srcform = testFormats[isrc]

  for idest in xrange (0, len (testFormats)):
    destform = testFormats[idest]

    # convert generated double floating point waveform to source format
    trans.set_formats (Ipatch.SampleWidth.DOUBLE | hostEndian, srcform,
                       Ipatch.SAMPLE_UNITY_CHANNEL_MAP)
    srcData = trans.convert (sampleData)

    # convert source format to destination format
    trans.set_formats (srcform, destform, Ipatch.SAMPLE_UNITY_CHANNEL_MAP)
    destData = trans.convert (srcData)

    # convert destination format to final double output
    trans.set_formats (destform, Ipatch.SampleWidth.DOUBLE | hostEndian,
                       Ipatch.SAMPLE_UNITY_CHANNEL_MAP)
    finalData = trans.convert (destData)
    finalDataArray = (ctypes.c_double * sampleSize).from_buffer_copy (finalData)

    maxdiff = 0.0
    maxindex = 0

    # compare final waveform against original
    for i in xrange (0, sampleSize):
      d = abs (sampleDataArray[i] - finalDataArray[i])

      if d > maxdiff:
        maxdiff = d
        maxindex = i

    if maxdiff > max_maxdiff:
      max_maxdiff = maxdiff

    if maxdiff <= MAX_DIFF_ALLOWED:
      Test.info ("Converted %s to %s: maxdiff=%0.6f, index=%d"
                 % (testFormatNames[isrc], testFormatNames[idest], maxdiff, maxindex))
    else:
      Test.error ("FAILED Converting %s to %s: maxdiff=%0.6f, index=%d"
                  % (testFormatNames[isrc], testFormatNames[idest], maxdiff, maxindex))
      failcount += 1

if failcount > 0:
  Test.error ("%d of %d format conversions FAILED (max diff=%0.6f)" % (failcount, len (testFormats) ** 2, max_maxdiff))
else: Test.msg ("All %d sample format conversions PASSED (max diff=%0.6f)" % (len (testFormats) ** 2, max_maxdiff))


Test.exit ()