from .utils import (
    db_to_float,
    ratio_to_db,
    register_pydub_effect,
    make_chunks,
)
from .exceptions import TooManyMissingFrames

@register_pydub_effect
def normalize(seg, headroom=0.1):
    """
    headroom is how close to the maximum volume to boost the signal up to (specified in dB)
    """
    peak_sample_val = seg.max
    target_peak = seg.max_possible_amplitude * db_to_float(-headroom)

    needed_boost = ratio_to_db(target_peak / peak_sample_val)
    return seg.apply_gain(needed_boost)
    
@register_pydub_effect
def speedup(seg, playback_speed=1.5, chunk_size=150, crossfade=25):
    # we will keep audio in 150ms chunks since one waveform at 20Hz is 50ms long 
    # (20 Hz is the lowest frequency audible to humans)
    
    # portion of AUDIO TO KEEP. if playback speed is 1.25 we keep 80% (0.8) and
    # discard 20% (0.2)
    atk = 1.0 / playback_speed
    
    if playback_speed < 2.0:    
        # throwing out more than half the audio - keep 50ms chunks
        ms_to_remove_per_chunk = int(chunk_size * (1 - atk) / atk)
    else:
        # throwing out less than half the audio - throw out 50ms chunks
        ms_to_remove_per_chunk = int(chunk_size)
        chunk_size = int(atk * chunk_size / (1 - atk))
    
    # the crossfade cannot be longer than the amound of audio we're removing
    crossfade = min(crossfade, ms_to_remove_per_chunk-1)
        
    print "chunk: {}, rm: {}".format(chunk_size, ms_to_remove_per_chunk)
    
    chunks = make_chunks(seg, chunk_size + ms_to_remove_per_chunk)
    if len(chunks) < 2:
        raise Exception("Could not speed up AudioSegment, it was too short {2:0.2f}s for the current settings:\n{0}ms chunks at {1:0.1f}x speedup".format(chunk_size, playback_speed, seg.duration_seconds))
    
    # we'll actually truncate a bit less than we calculated to make up for the
    # crossfade between chunks
    ms_to_remove_per_chunk -= crossfade

    # we don't want to truncate the last chunk since it is not guaranteed to be
    # the full chunk length
    last_chunk_i = len(chunks) - 1
    chunks = [chunk[:-ms_to_remove_per_chunk] 
              for (i, chunk) in enumerate(chunks)
              if i < last_chunk_i]
    
    out = chunks[0]
    for chunk in chunks[1:-1]:
        out = out.append(chunk, crossfade=crossfade)
        
    out = out.append(chunk, crossfade=min(crossfade, len(chunk)))
    return out
    
from .utils import (
    db_to_float,
    ratio_to_db,
    register_pydub_effect,
    make_chunks,
)
from .exceptions import TooManyMissingFrames

@register_pydub_effect
def normalize(seg, headroom=0.1):
    """
    headroom is how close to the maximum volume to boost the signal up to (specified in dB)
    """
    peak_sample_val = seg.max
    target_peak = seg.max_possible_amplitude * db_to_float(-headroom)

    needed_boost = ratio_to_db(target_peak / peak_sample_val)
    return seg.apply_gain(needed_boost)
    
@register_pydub_effect
def speedup(seg, playback_speed=1.5, chunk_size=150, crossfade=25):
    # we will keep audio in 150ms chunks since one waveform at 20Hz is 50ms long 
    # (20 Hz is the lowest frequency audible to humans)
    
    # portion of AUDIO TO KEEP. if playback speed is 1.25 we keep 80% (0.8) and
    # discard 20% (0.2)
    atk = 1.0 / playback_speed
    
    if playback_speed < 2.0:    
        # throwing out more than half the audio - keep 50ms chunks
        ms_to_remove_per_chunk = int(chunk_size * (1 - atk) / atk)
    else:
        # throwing out less than half the audio - throw out 50ms chunks
        ms_to_remove_per_chunk = int(chunk_size)
        chunk_size = int(atk * chunk_size / (1 - atk))
    
    # the crossfade cannot be longer than the amound of audio we're removing
    crossfade = min(crossfade, ms_to_remove_per_chunk-1)
        
    print("chunk: {}, rm: {}".format(chunk_size, ms_to_remove_per_chunk))
    
    chunks = make_chunks(seg, chunk_size + ms_to_remove_per_chunk)
    if len(chunks) < 2:
        raise Exception("Could not speed up AudioSegment, it was too short {2:0.2f}s for the current settings:\n{0}ms chunks at {1:0.1f}x speedup".format(chunk_size, playback_speed, seg.duration_seconds))
    
    # we'll actually truncate a bit less than we calculated to make up for the
    # crossfade between chunks
    ms_to_remove_per_chunk -= crossfade

    # we don't want to truncate the last chunk since it is not guaranteed to be
    # the full chunk length
    last_chunk_i = len(chunks) - 1
    chunks = [chunk[:-ms_to_remove_per_chunk] 
              for (i, chunk) in enumerate(chunks)
              if i < last_chunk_i]
    
    out = chunks[0]
    for chunk in chunks[1:-1]:
        out = out.append(chunk, crossfade=crossfade)
        
    out = out.append(chunk, crossfade=min(crossfade, len(chunk)))
    return out
    

print should be called as a function for python 3 compatibility