/test/test.py

https://github.com/xuanhan863/pydub · Python · 219 lines · 139 code · 78 blank · 2 comment · 6 complexity · 324a524a6589bcbb18113e1267d2e3b2 MD5 · raw file

  1. import unittest
  2. import os
  3. from pydub import AudioSegment
  4. from pydub.utils import db_to_float, ratio_to_db
  5. data_dir = os.path.join(os.path.dirname(__file__), 'data')
  6. class UtilityTests(unittest.TestCase):
  7. def test_db_float_conversions(self):
  8. self.assertEqual(db_to_float(10), 10)
  9. self.assertEqual(db_to_float(0), 1)
  10. self.assertEqual(ratio_to_db(1), 0)
  11. self.assertEqual(ratio_to_db(10), 10)
  12. self.assertEqual(3, db_to_float(ratio_to_db(3)))
  13. self.assertEqual(12, ratio_to_db(db_to_float(12)))
  14. class FileAccessTests(unittest.TestCase):
  15. def setUp(self):
  16. self.mp3_path = os.path.join(data_dir, 'test1.mp3')
  17. def test_audio_segment_from_mp3(self):
  18. seg1 = AudioSegment.from_mp3(os.path.join(data_dir, 'test1.mp3'))
  19. mp3_file = open(os.path.join(data_dir, 'test1.mp3'), 'rb')
  20. seg2 = AudioSegment.from_mp3(mp3_file)
  21. self.assertEqual(len(seg1), len(seg2))
  22. self.assertTrue(seg1._data == seg2._data)
  23. self.assertTrue(len(seg1) > 0)
  24. test1 = test2 = test3 = None
  25. class AudioSegmentTests(unittest.TestCase):
  26. def setUp(self):
  27. global test1, test2, test3
  28. if not test1:
  29. test1 = AudioSegment.from_mp3(os.path.join(data_dir, 'test1.mp3'))
  30. test2 = AudioSegment.from_mp3(os.path.join(data_dir, 'test2.mp3'))
  31. test3 = AudioSegment.from_mp3(os.path.join(data_dir, 'test3.mp3'))
  32. self.seg1, self.seg2, self.seg3 = test1, test2, test3
  33. def assertWithinRange(self, val, lower_bound, upper_bound):
  34. self.assertTrue(lower_bound < val < upper_bound, "%s is not in the acceptable range: %s - %s" % (val, lower_bound, upper_bound))
  35. def assertWithinTolerance(self, val, expected, tolerance=None, percentage=None):
  36. if percentage is not None:
  37. tolerance = val * percentage
  38. lower_bound = val - tolerance
  39. upper_bound = val + tolerance
  40. self.assertWithinRange(val, lower_bound, upper_bound)
  41. def test_concat(self):
  42. catted_audio = self.seg1 + self.seg2
  43. expected = len(self.seg1) + len(self.seg2)
  44. self.assertWithinTolerance(len(catted_audio), expected, 1)
  45. def test_append(self):
  46. merged1 = self.seg3.append(self.seg1, crossfade=100)
  47. merged2 = self.seg3.append(self.seg2, crossfade=100)
  48. self.assertEqual(len(merged1), len(self.seg1) + len(self.seg3) - 100)
  49. self.assertEqual(len(merged2), len(self.seg2) + len(self.seg3) - 100)
  50. def test_volume_with_add_sub(self):
  51. quieter = self.seg1 - 6
  52. self.assertAlmostEqual(ratio_to_db(quieter.rms, self.seg1.rms), -6)
  53. louder = quieter + 2.5
  54. self.assertAlmostEqual(ratio_to_db(louder.rms, quieter.rms), 2.5)
  55. def test_repeat_with_multiply(self):
  56. seg = self.seg1 * 3
  57. expected = len(self.seg1) * 3
  58. expected = (expected-2, expected+2)
  59. self.assertTrue(expected[0] < len(seg) < expected[1])
  60. def test_overlay(self):
  61. seg_mult = self.seg1[:5000] * self.seg2[:3000]
  62. seg_over = self.seg1[:5000].overlay(self.seg2[:3000], loop=True)
  63. self.assertEqual(len(seg_mult), len(seg_over))
  64. self.assertTrue(seg_mult._data == seg_over._data)
  65. self.assertEqual(len(seg_mult), 5000)
  66. self.assertEqual(len(seg_over), 5000)
  67. def test_slicing(self):
  68. empty = self.seg1[:0]
  69. second_long_slice = self.seg1[:1000]
  70. remainder = self.seg1[1000:]
  71. self.assertEqual(len(empty), 0)
  72. self.assertEqual(len(second_long_slice), 1000)
  73. self.assertEqual(len(remainder), len(self.seg1) - 1000)
  74. last_5_seconds = self.seg1[-5000:]
  75. before = self.seg1[:-5000]
  76. self.assertEqual(len(last_5_seconds), 5000)
  77. self.assertEqual(len(before), len(self.seg1) - 5000)
  78. past_end = second_long_slice[:1500]
  79. self.assertTrue(second_long_slice._data == past_end._data)
  80. def test_indexing(self):
  81. short = self.seg1[:100]
  82. rebuilt1 = self.seg1[:0]
  83. for part in short:
  84. rebuilt1 += part
  85. rebuilt2 = sum([part for part in short], short[:0])
  86. self.assertTrue(short._data == rebuilt1._data)
  87. self.assertTrue(short._data == rebuilt2._data)
  88. def test_set_channels(self):
  89. mono = self.seg1.set_channels(1)
  90. stereo = mono.set_channels(2)
  91. self.assertEqual(len(self.seg1), len(mono))
  92. self.assertEqual(len(self.seg1), len(stereo))
  93. mono = self.seg2.set_channels(1)
  94. mono = mono.set_frame_rate(22050)
  95. self.assertEqual(len(mono), len(self.seg2))
  96. monomp3 = AudioSegment.from_mp3(mono.export())
  97. self.assertWithinTolerance(len(monomp3), len(self.seg2), percentage=0.01)
  98. merged = monomp3.append(stereo, crossfade=100)
  99. self.assertWithinTolerance(len(merged), len(self.seg1)+len(self.seg2)-100, tolerance=1)
  100. def test_export(self):
  101. seg = self.seg1 + self.seg2
  102. exported_mp3 = seg.export()
  103. exported = AudioSegment.from_mp3(exported_mp3)
  104. self.assertWithinTolerance(len(exported), len(seg), percentage=0.01)
  105. def test_fades(self):
  106. seg = self.seg1[:10000]
  107. # 1 ms difference in the position of the end of the fade out
  108. inf_end = seg.fade(start=0, end=float('inf'), to_gain=-120)
  109. negative_end = seg.fade(start=0, end=-1, to_gain=-120)
  110. self.assertWithinTolerance(inf_end.rms, negative_end.rms, percentage=0.001)
  111. self.assertTrue(negative_end.rms < inf_end.rms)
  112. self.assertTrue(inf_end.rms < seg.rms)
  113. self.assertEqual(len(inf_end), len(seg))
  114. self.assertTrue(-3 < ratio_to_db(inf_end.rms, seg.rms) < -2)
  115. # use a slice out of the middle to make sure there is audio
  116. seg = self.seg2[20000:30000]
  117. fade_out = seg.fade_out(5000)
  118. fade_in = seg.fade_in(5000)
  119. self.assertTrue(0 < fade_out.rms < seg.rms)
  120. self.assertTrue(0 < fade_in.rms < seg.rms)
  121. self.assertEqual(len(fade_out), len(seg))
  122. self.assertEqual(len(fade_in), len(seg))
  123. db_at_beginning = ratio_to_db(fade_in[:1000].rms, seg[:1000].rms)
  124. db_at_end = ratio_to_db(fade_in[-1000:].rms, seg[-1000:].rms)
  125. self.assertTrue(db_at_beginning < db_at_end)
  126. db_at_beginning = ratio_to_db(fade_out[:1000].rms, seg[:1000].rms)
  127. db_at_end = ratio_to_db(fade_out[-1000:].rms, seg[-1000:].rms)
  128. self.assertTrue(db_at_end < db_at_beginning)
  129. def test_for_accidental_shortening(self):
  130. seg = AudioSegment.from_mp3(os.path.join(data_dir, 'party.mp3'))
  131. seg.export('tmp.mp3')
  132. for i in range(10):
  133. AudioSegment.from_mp3('tmp.mp3').export('tmp.mp3', "mp3")
  134. tmp = AudioSegment.from_mp3('tmp.mp3')
  135. os.unlink('tmp.mp3')
  136. self.assertEqual(len(tmp), len(seg))
  137. def test_formats(self):
  138. seg_m4a = AudioSegment.from_file(os.path.join(data_dir, 'format_test.m4a'), "m4a")
  139. self.assertTrue(len(seg_m4a))
  140. if __name__ == "__main__":
  141. unittest.main()