我刚刚开始学习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)
上面的代码运行良好,并且得到了以下格式的波形:
以上格式类似于使用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吗?