python中的等时音调的拍频变化

时间:2018-09-13 07:13:48

标签: python python-3.x

我刚刚开始学习isochronic tones,并开始编写基本的Python脚本以生成相同的内容。以下是我为执行以下操作而编写的脚本:

  • 生成拍频的梯形波
  • 用拍频的梯形波调制基频的正弦波

    #!/usr/bin/env python
    # encoding: utf-8
    
    """
    Small program for creating Isochronic Tones of desired base frequency, beat frequency and ramp frequencies
    """
    
    import math
    import wave
    import struct
    import array
    import sys
    
    def make_isochronic_wave(beat_freq, beat_ramp_percent, beat_sampl_rate, beat_time, base_freq, amplitude):
    
    #
    # The time for which the trapezoidal beat frequency wave is present in the entire cycle
    #
    up_time = 1 / beat_freq
    
    #
    # Gap between consequtive trapezoidal beats
    #
    gap_percent = up_time * 0.15
    
    #
    # To accomodate gaps
    #
    up_time = up_time * 0.85
    
    #
    # Total number of samples
    #
    data_size = beat_sampl_rate * beat_time
    
    #
    # No. of gaps per sec = No. of beats per sec
    #
    no_of_gaps = beat_freq
    
    #
    # Samples per gap = percentage of total time allocated for gaps * No. of samples per sec
    #
    sampls_per_gap = gap_percent * beat_sampl_rate
    
    #
    # Total number of samples in all the gaps
    #
    gap_sampls = no_of_gaps * sampls_per_gap
    
    #
    # Change the beat sample rate to accomodate gaps
    #
    beat_sampl_rate = beat_sampl_rate - gap_sampls
    
    #
    # nsps = Number of Samples Per Second
    #
    # NOTE: Please see the image at: 
    #
    beat_nsps_defined = beat_sampl_rate * up_time
    
    beat_nsps_inc = beat_nsps_defined * beat_ramp_percent
    
    beat_nsps_dec = beat_nsps_defined * beat_ramp_percent
    
    beat_nsps_stable = beat_nsps_defined - (beat_nsps_inc + beat_nsps_dec)
    
    beat_nsps_undefined = beat_sampl_rate - beat_nsps_defined
    
    #
    # Trapezoidal values
    #
    values = []
    
    #
    # Trapezoidal * sine == Isochronic values
    #
    isoch_values = []
    
    #
    # Samples constructed
    #
    sampls_const = 0
    
    #
    # Iterate till all the samples in data_size are constructed
    #
    while sampls_const < data_size:
        prev_sampl_value_inc = 0.0
        prev_sampl_value_dec = 1.0
        #
        # Construct one trapezoidal beat wave (remember this is not the entire sample)
        #
        for sampl_itr in range(0, int(beat_sampl_rate)):
            if sampl_itr < beat_nsps_inc:
                value = prev_sampl_value_inc + (1 / beat_nsps_inc)
                prev_sampl_value_inc = value
                values.append(value)
            if sampl_itr > beat_nsps_inc:
                if sampl_itr < (beat_nsps_inc + beat_nsps_stable):
                    value = 1
                    values.append(value)
                elif (sampl_itr > (beat_nsps_inc + beat_nsps_stable)) and (sampl_itr < (beat_nsps_inc + beat_nsps_stable + beat_nsps_dec)):
                    value = prev_sampl_value_dec - (1 / beat_nsps_dec)
                    prev_sampl_value_dec = value
                    values.append(value)
    
        #
        # Add the gap cycles
        #
        for gap_iter in range(0, int(sampls_per_gap)):
            values.append(0)
    
        #
        # Increment the number of samples constructed to reflect the values
        #
        sampls_const = sampls_const + beat_nsps_defined + gap_sampls
    
    #
    # Open the wave file
    #
    wav_file = wave.open("beat_wave_%s_%s.wav" % (base_freq, beat_freq), "w")
    
    #
    # Define parameters
    #
    nchannels = 2
    sampwidth = 2
    framerate = beat_sampl_rate
    nframes = data_size
    comptype = "NONE"
    compname = "not compressed"
    
    wav_file.setparams((nchannels, sampwidth, framerate, nframes, comptype, compname))
    
    #
    # Calculate isochronic wave point values
    #
    value_iter = 0
    
    for value in values:
        isoch_value = value * math.sin(2 * math.pi * base_freq * (value_iter / beat_sampl_rate))
        value_iter = value_iter + 1
        isoch_values.append(isoch_value)
    
    #
    # Create the wave file (in .wav format)
    #
    for value in isoch_values:
        data = array.array('h')
        data.append(int(value * amplitude / 2)) # left channel
        data.append(int(value * amplitude / 2)) # right channel
    
        wav_file.writeframes(data.tostring())
    
    
    wav_file.close()
    
    try:
        base_freq = int(sys.argv[1], 10)
        beat_freq = int(sys.argv[2], 10)
        sample_rate = int(sys.argv[3], 10)
        output_time = int(sys.argv[4], 10)
        ramp_percent = float(sys.argv[5])
        amplitude = float(sys.argv[6])
    
        make_isochronic_wave(beat_freq, ramp_percent, sample_rate, output_time, base_freq, amplitude)
    except:
        msg = """
    <program> <base freqency> <beat frequency> <sample rate> <output time> <ramp percent> <amplitude>
    """
        print (msg)
    

上面的代码运行良好,并且得到了以下格式的波形:

Generated Isochronic Tones

以上格式类似于使用IsoMod插件使用audacity生成的格式。但是,我想产生一种拍频,该拍频的拍频会降低。为此,我增强了上面的脚本,以每秒一次的循环调用梯形波的产生。但是,将wav文件的参数设置为多次写入(由于跨斜坡的beat_freq的变化而导致data_size的变化),我得到了以下错误

G:\>python gen_isochronic_tones.py 70 10 5 11025 5 0.15 8000
gen_isochronic_tones.py:195: DeprecationWarning: tostring() is deprecated. Use tobytes() instead.
  make_isochronic_wave(beat_freq_start, beat_freq_end, ramp_percent, sample_rate, output_time, base_freq, amplitude)
Traceback (most recent call last):
  File "gen_isochronic_tones.py", line 195, in <module>
    make_isochronic_wave(beat_freq_start, beat_freq_end, ramp_percent, sample_rate, output_time, base_freq, amplitude)
  File "gen_isochronic_tones.py", line 156, in make_isochronic_wave
    wav_file.setparams((nchannels, sampwidth, framerate, data_size, comptype, compname))
  File "G:\Python37-32\lib\wave.py", line 399, in setparams
    raise Error('cannot change parameters after starting to write')
wave.Error: cannot change parameters after starting to write

像wave模块一样,允许参数(即上面的data_size)仅更改一次。知道如何使它能够更改data_size吗?

0 个答案:

没有答案