Repository: jiaaro/pydub

Issue:
Error when attempting to crossfade with duration longer than one of the files
### Steps to reproduce
Create an audio segment from a sound file.  Attempt to append a second sound file, with a crossfade duration longer than the actual sound file.

### Expected behavior
Either an error message that explains the issue, or a default to crossfading with the maximum length that would be possible.

### Actual behavior
A TooManyMissingFrames exception is thrown from an unintuitive place.

### Your System configuration
- Python version: 3.5.2
- Pydub version: 0.18.0
- ffmpeg or avlib?: ffmpeg
- ffmpeg/avlib version: 2.8.11-0ubuntu0.16.04.1



Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5785b1..5b92988 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,7 @@
 # v0.20.0
-- Add new parameter `gain_during_overlay` to `pydub.AudioSegment.overlay` which allows users to adjust the volume of the target AudioSegment during the portion of the segment which is overlaid with the additional AudioSegment. 
+- Add new parameter `gain_during_overlay` to `pydub.AudioSegment.overlay` which allows users to adjust the volume of the target AudioSegment during the portion of the segment which is overlaid with the additional AudioSegment.
+- `pydub.playback.play()` No longer displays the (very verbose) playback "banner" when using ffplay
+- Fix a confusing error message when using invalid crossfade durations (issue #193)
 
 # v0.19.0
 - Allow codec and ffmpeg/avconv parameters to be set in the `pydub.AudioSegment.from_file()` for more control while decoding audio files
diff --git a/pydub/audio_segment.py b/pydub/audio_segment.py
index 2ad6dd9..5d497b9 100644
--- a/pydub/audio_segment.py
+++ b/pydub/audio_segment.py
@@ -488,7 +488,7 @@ class AudioSegment(object):
         if codec:
             # force audio decoder
             conversion_command += ["-acodec", codec]
-            
+
         conversion_command += [
             "-i", input_file.name,  # input_file options (filename last)
             "-vn",  # Drop any video streams if there are any
@@ -943,6 +943,14 @@ class AudioSegment(object):
 
         if not crossfade:
             return seg1._spawn(seg1._data + seg2._data)
+        elif crossfade > len(self):
+            raise ValueError("Crossfade is longer than the original AudioSegment ({}ms > {}ms)".format(
+                crossfade, len(self)
+            ))
+        elif crossfade > len(seg):
+            raise ValueError("Crossfade is longer than the appended AudioSegment ({}ms > {}ms)".format(
+                crossfade, len(seg)
+            ))
 
         xf = seg1[-crossfade:].fade(to_gain=-120, start=0, end=float('inf'))
         xf *= seg2[:crossfade].fade(from_gain=-120, start=0, end=float('inf'))
diff --git a/pydub/playback.py b/pydub/playback.py
index ae392ee..a162152 100644
--- a/pydub/playback.py
+++ b/pydub/playback.py
@@ -1,7 +1,7 @@
 """
 Support for playing AudioSegments. Pyaudio will be used if it's installed,
 otherwise will fallback to ffplay. Pyaudio is a *much* nicer solution, but
-is tricky to install. See my notes on installing pyaudio in a virtualenv (on 
+is tricky to install. See my notes on installing pyaudio in a virtualenv (on
 OSX 10.10): https://gist.github.com/jiaaro/9767512210a1d80a8a0d
 """
 
@@ -23,7 +23,7 @@ def _play_with_pyaudio(seg):
     import pyaudio
 
     p = pyaudio.PyAudio()
-    stream = p.open(format=p.get_format_from_width(seg.sample_width),  
+    stream = p.open(format=p.get_format_from_width(seg.sample_width),
                     channels=seg.channels,
                     rate=seg.frame_rate,
                     output=True)
@@ -32,10 +32,10 @@ def _play_with_pyaudio(seg):
     for chunk in make_chunks(seg, 500):
         stream.write(chunk._data)
 
-    stream.stop_stream()  
-    stream.close()  
+    stream.stop_stream()
+    stream.close()
 
-    p.terminate()  
+    p.terminate()
 
 
 def play(audio_segment):
diff --git a/setup.py b/setup.py
index 1f191b1..b9b8162 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@ from setuptools import setup
 
 setup(
     name='pydub',
-    version='0.19.0',
+    version='0.20.0',
     author='James Robert',
     author_email='jiaaro@gmail.com',
     description='Manipulate audio with an simple and easy high level interface',


Test patch:
diff --git a/test/test.py b/test/test.py
index f42b722..9eea471 100644
--- a/test/test.py
+++ b/test/test.py
@@ -142,6 +142,11 @@ class AudioSegmentTests(unittest.TestCase):
         self.assertEqual(len(merged1), len(self.seg1) + len(self.seg3) - 100)
         self.assertEqual(len(merged2), len(self.seg2) + len(self.seg3) - 100)
 
+    def test_too_long_crossfade(self):
+        s1 = self.seg1[:1000]
+        s2 = self.seg2[:500]
+        self.assertRaises(ValueError, lambda: s1.append(s2, crossfade=len(s1) + 10))
+
     def test_sum(self):
         def gen():
             yield self.seg1