]>
Commit | Line | Data |
---|---|---|
4710c53d | 1 | from test import test_support\r |
2 | test_support.requires('audio')\r | |
3 | \r | |
4 | from test.test_support import findfile\r | |
5 | \r | |
6 | ossaudiodev = test_support.import_module('ossaudiodev')\r | |
7 | \r | |
8 | import errno\r | |
9 | import sys\r | |
10 | import sunau\r | |
11 | import time\r | |
12 | import audioop\r | |
13 | import unittest\r | |
14 | \r | |
15 | # Arggh, AFMT_S16_NE not defined on all platforms -- seems to be a\r | |
16 | # fairly recent addition to OSS.\r | |
17 | try:\r | |
18 | from ossaudiodev import AFMT_S16_NE\r | |
19 | except ImportError:\r | |
20 | if sys.byteorder == "little":\r | |
21 | AFMT_S16_NE = ossaudiodev.AFMT_S16_LE\r | |
22 | else:\r | |
23 | AFMT_S16_NE = ossaudiodev.AFMT_S16_BE\r | |
24 | \r | |
25 | \r | |
26 | def read_sound_file(path):\r | |
27 | with open(path, 'rb') as fp:\r | |
28 | au = sunau.open(fp)\r | |
29 | rate = au.getframerate()\r | |
30 | nchannels = au.getnchannels()\r | |
31 | encoding = au._encoding\r | |
32 | fp.seek(0)\r | |
33 | data = fp.read()\r | |
34 | \r | |
35 | if encoding != sunau.AUDIO_FILE_ENCODING_MULAW_8:\r | |
36 | raise RuntimeError("Expect .au file with 8-bit mu-law samples")\r | |
37 | \r | |
38 | # Convert the data to 16-bit signed.\r | |
39 | data = audioop.ulaw2lin(data, 2)\r | |
40 | return (data, rate, 16, nchannels)\r | |
41 | \r | |
42 | class OSSAudioDevTests(unittest.TestCase):\r | |
43 | \r | |
44 | def play_sound_file(self, data, rate, ssize, nchannels):\r | |
45 | try:\r | |
46 | dsp = ossaudiodev.open('w')\r | |
47 | except IOError, msg:\r | |
48 | if msg.args[0] in (errno.EACCES, errno.ENOENT,\r | |
49 | errno.ENODEV, errno.EBUSY):\r | |
50 | raise unittest.SkipTest(msg)\r | |
51 | raise\r | |
52 | \r | |
53 | # at least check that these methods can be invoked\r | |
54 | dsp.bufsize()\r | |
55 | dsp.obufcount()\r | |
56 | dsp.obuffree()\r | |
57 | dsp.getptr()\r | |
58 | dsp.fileno()\r | |
59 | \r | |
60 | # Make sure the read-only attributes work.\r | |
61 | self.assertFalse(dsp.closed)\r | |
62 | self.assertEqual(dsp.name, "/dev/dsp")\r | |
63 | self.assertEqual(dsp.mode, "w", "bad dsp.mode: %r" % dsp.mode)\r | |
64 | \r | |
65 | # And make sure they're really read-only.\r | |
66 | for attr in ('closed', 'name', 'mode'):\r | |
67 | try:\r | |
68 | setattr(dsp, attr, 42)\r | |
69 | except TypeError:\r | |
70 | pass\r | |
71 | else:\r | |
72 | self.fail("dsp.%s not read-only" % attr)\r | |
73 | \r | |
74 | # Compute expected running time of sound sample (in seconds).\r | |
75 | expected_time = float(len(data)) / (ssize//8) / nchannels / rate\r | |
76 | \r | |
77 | # set parameters based on .au file headers\r | |
78 | dsp.setparameters(AFMT_S16_NE, nchannels, rate)\r | |
79 | self.assertTrue(abs(expected_time - 3.51) < 1e-2, expected_time)\r | |
80 | t1 = time.time()\r | |
81 | dsp.write(data)\r | |
82 | dsp.close()\r | |
83 | t2 = time.time()\r | |
84 | elapsed_time = t2 - t1\r | |
85 | \r | |
86 | percent_diff = (abs(elapsed_time - expected_time) / expected_time) * 100\r | |
87 | self.assertTrue(percent_diff <= 10.0,\r | |
88 | "elapsed time > 10% off of expected time")\r | |
89 | \r | |
90 | def set_parameters(self, dsp):\r | |
91 | # Two configurations for testing:\r | |
92 | # config1 (8-bit, mono, 8 kHz) should work on even the most\r | |
93 | # ancient and crufty sound card, but maybe not on special-\r | |
94 | # purpose high-end hardware\r | |
95 | # config2 (16-bit, stereo, 44.1kHz) should work on all but the\r | |
96 | # most ancient and crufty hardware\r | |
97 | config1 = (ossaudiodev.AFMT_U8, 1, 8000)\r | |
98 | config2 = (AFMT_S16_NE, 2, 44100)\r | |
99 | \r | |
100 | for config in [config1, config2]:\r | |
101 | (fmt, channels, rate) = config\r | |
102 | if (dsp.setfmt(fmt) == fmt and\r | |
103 | dsp.channels(channels) == channels and\r | |
104 | dsp.speed(rate) == rate):\r | |
105 | break\r | |
106 | else:\r | |
107 | raise RuntimeError("unable to set audio sampling parameters: "\r | |
108 | "you must have really weird audio hardware")\r | |
109 | \r | |
110 | # setparameters() should be able to set this configuration in\r | |
111 | # either strict or non-strict mode.\r | |
112 | result = dsp.setparameters(fmt, channels, rate, False)\r | |
113 | self.assertEqual(result, (fmt, channels, rate),\r | |
114 | "setparameters%r: returned %r" % (config, result))\r | |
115 | \r | |
116 | result = dsp.setparameters(fmt, channels, rate, True)\r | |
117 | self.assertEqual(result, (fmt, channels, rate),\r | |
118 | "setparameters%r: returned %r" % (config, result))\r | |
119 | \r | |
120 | def set_bad_parameters(self, dsp):\r | |
121 | # Now try some configurations that are presumably bogus: eg. 300\r | |
122 | # channels currently exceeds even Hollywood's ambitions, and\r | |
123 | # negative sampling rate is utter nonsense. setparameters() should\r | |
124 | # accept these in non-strict mode, returning something other than\r | |
125 | # was requested, but should barf in strict mode.\r | |
126 | fmt = AFMT_S16_NE\r | |
127 | rate = 44100\r | |
128 | channels = 2\r | |
129 | for config in [(fmt, 300, rate), # ridiculous nchannels\r | |
130 | (fmt, -5, rate), # impossible nchannels\r | |
131 | (fmt, channels, -50), # impossible rate\r | |
132 | ]:\r | |
133 | (fmt, channels, rate) = config\r | |
134 | result = dsp.setparameters(fmt, channels, rate, False)\r | |
135 | self.assertNotEqual(result, config,\r | |
136 | "unexpectedly got requested configuration")\r | |
137 | \r | |
138 | try:\r | |
139 | result = dsp.setparameters(fmt, channels, rate, True)\r | |
140 | except ossaudiodev.OSSAudioError, err:\r | |
141 | pass\r | |
142 | else:\r | |
143 | self.fail("expected OSSAudioError")\r | |
144 | \r | |
145 | def test_playback(self):\r | |
146 | sound_info = read_sound_file(findfile('audiotest.au'))\r | |
147 | self.play_sound_file(*sound_info)\r | |
148 | \r | |
149 | def test_set_parameters(self):\r | |
150 | dsp = ossaudiodev.open("w")\r | |
151 | try:\r | |
152 | self.set_parameters(dsp)\r | |
153 | \r | |
154 | # Disabled because it fails under Linux 2.6 with ALSA's OSS\r | |
155 | # emulation layer.\r | |
156 | #self.set_bad_parameters(dsp)\r | |
157 | finally:\r | |
158 | dsp.close()\r | |
159 | self.assertTrue(dsp.closed)\r | |
160 | \r | |
161 | \r | |
162 | def test_main():\r | |
163 | try:\r | |
164 | dsp = ossaudiodev.open('w')\r | |
165 | except (ossaudiodev.error, IOError), msg:\r | |
166 | if msg.args[0] in (errno.EACCES, errno.ENOENT,\r | |
167 | errno.ENODEV, errno.EBUSY):\r | |
168 | raise unittest.SkipTest(msg)\r | |
169 | raise\r | |
170 | dsp.close()\r | |
171 | test_support.run_unittest(__name__)\r | |
172 | \r | |
173 | if __name__ == "__main__":\r | |
174 | test_main()\r |