在一定持续时间内重复修改声音音调的算法和包
Algorithm and package to modify the pitch of the sound for certain durations repeatedly
我想使用现有的音频文件创建一个音频文件,通过它我可以为文件的不同持续时间修改音频的音调。就像如果文件是 36 秒,那么我想用某个值修改第 1 2 秒的音高,然后从第 6 秒到第 9 秒修改一些其他值,依此类推。
基本上,我试图根据消息中的每个字符 k、i、l、b...我采用了一个存储不同持续时间的数组,就像我有 26 个字母 a、b、c、d... 的 table 等等。基于这些持续时间,我正在尝试修改这些特定持续时间的文件。问题是我对音频的实际操作不是很好,我什至在 Java 中尝试过同样的操作,但无法做到。
是否有一些其他参数可以在音频文件中更改而不会使更改太明显?
我指的是这些值,虽然代码在 Java 但忽略它。我稍后会在 Python 中对其进行转换。值以毫秒为单位。
public static void convertMsgToAudio(String msg){
int len = msg.length();
duration = new double[len];
msg = msg.toUpperCase();
System.out.println("Msg 2 : " + msg);
int i;
//char ch;
for(i=0;i<msg.length();i++){
if(msg.charAt(i) == 'A'){
duration[i] = 50000;
}
else if (msg.charAt(i) == 'B'){
duration[i] = 100000; // value in milliseconds
}
else if (msg.charAt(i) == 'C'){
duration[i] = 150000;
}
else if (msg.charAt(i) == 'D'){
duration[i] = 200000;
}
else if (msg.charAt(i) == 'E'){
duration[i] = 250000;
}
else if (msg.charAt(i) == 'F'){
duration[i] = 300000;
}
else if (msg.charAt(i) == 'G'){
duration[i] = 350000;
}
else if (msg.charAt(i) == 'H'){
duration[i] = 400000;
}
else if (msg.charAt(i) == 'I'){
duration[i] = 450000;
}
else if (msg.charAt(i) == 'J'){
duration[i] = 500000;
}
else if (msg.charAt(i) == 'K'){
duration[i] = 550000;
}
else if (msg.charAt(i) == 'L'){
duration[i] = 600000;
}
else if (msg.charAt(i) == 'M'){
duration[i] = 650000;
}
else if (msg.charAt(i) == 'N'){
duration[i] = 700000;
}
else if (msg.charAt(i) == 'O'){
duration[i] = 750000;
}
else if (msg.charAt(i) == 'P'){
duration[i] = 800000;
}
else if (msg.charAt(i) == 'Q'){
duration[i] = 850000;
}
else if (msg.charAt(i) == 'R'){
duration[i] = 900000;
}
else if (msg.charAt(i) == 'S'){
duration[i] = 950000;
}
else if (msg.charAt(i) == 'T'){
duration[i] = 1000000;
}
else if (msg.charAt(i) == 'U'){
duration[i] = 1100000;
}
else if (msg.charAt(i) == 'V'){
duration[i] = 1200000;
}
else if (msg.charAt(i) == 'W'){
duration[i] = 1300000;
}
else if (msg.charAt(i) == 'X'){
duration[i] = 1400000;
}
else if (msg.charAt(i) == 'Y'){
duration[i] = 1500000;
}
else if (msg.charAt(i) == 'Z'){
duration[i] = 1600000;
}
}
}
现在,我正尝试在 Python 中做同样的事情。我对这个概念很陌生,但这是我第一次遇到这个概念的问题。
一种简单的方法是直接处理原始 PCM 数据;在这种格式中,音频数据只是一系列 -32768...32767 值,每个条目存储为 2 个字节(假设 16 位有符号,单声道),并定期采样(例如 44100Hz)。
要改变音高,您可以 "read" 更快地获取此数据,例如在 45000Hz 或 43000Hz,这很容易通过重采样程序完成。例如
import struct
data = open("pcm.raw", "rb").read()
parsed = struct.unpack("%ih" % (len(data)//2), data)
# Here parsed is an array of numbers
pos = 0.0 # position in the source file
speed = 1.0 # current read speed = original sampling speed
result = []
while pos < len(parsed)-1:
# Compute a new sample (linear interpolation)
ip = int(pos)
v = int(parsed[ip] + (pos - ip)*(parsed[ip+1] - parsed[ip]))
result.append(v)
pos += speed # Next position
speed += 0.0001 # raise the pitch
# write the result to disk
open("out.raw", "wb").write(struct.pack("%ih" % len(result)), result)
这是解决该问题的一种非常非常简单的方法,但请注意,例如增加间距会缩短长度,为了避免这种情况,需要比插值更复杂的数学运算。
例如,我使用这种方法将一首歌曲的长度提高一个音调(我想看看这是否很明显……事实并非如此)。
我想使用现有的音频文件创建一个音频文件,通过它我可以为文件的不同持续时间修改音频的音调。就像如果文件是 36 秒,那么我想用某个值修改第 1 2 秒的音高,然后从第 6 秒到第 9 秒修改一些其他值,依此类推。
基本上,我试图根据消息中的每个字符 k、i、l、b...我采用了一个存储不同持续时间的数组,就像我有 26 个字母 a、b、c、d... 的 table 等等。基于这些持续时间,我正在尝试修改这些特定持续时间的文件。问题是我对音频的实际操作不是很好,我什至在 Java 中尝试过同样的操作,但无法做到。
是否有一些其他参数可以在音频文件中更改而不会使更改太明显?
我指的是这些值,虽然代码在 Java 但忽略它。我稍后会在 Python 中对其进行转换。值以毫秒为单位。
public static void convertMsgToAudio(String msg){
int len = msg.length();
duration = new double[len];
msg = msg.toUpperCase();
System.out.println("Msg 2 : " + msg);
int i;
//char ch;
for(i=0;i<msg.length();i++){
if(msg.charAt(i) == 'A'){
duration[i] = 50000;
}
else if (msg.charAt(i) == 'B'){
duration[i] = 100000; // value in milliseconds
}
else if (msg.charAt(i) == 'C'){
duration[i] = 150000;
}
else if (msg.charAt(i) == 'D'){
duration[i] = 200000;
}
else if (msg.charAt(i) == 'E'){
duration[i] = 250000;
}
else if (msg.charAt(i) == 'F'){
duration[i] = 300000;
}
else if (msg.charAt(i) == 'G'){
duration[i] = 350000;
}
else if (msg.charAt(i) == 'H'){
duration[i] = 400000;
}
else if (msg.charAt(i) == 'I'){
duration[i] = 450000;
}
else if (msg.charAt(i) == 'J'){
duration[i] = 500000;
}
else if (msg.charAt(i) == 'K'){
duration[i] = 550000;
}
else if (msg.charAt(i) == 'L'){
duration[i] = 600000;
}
else if (msg.charAt(i) == 'M'){
duration[i] = 650000;
}
else if (msg.charAt(i) == 'N'){
duration[i] = 700000;
}
else if (msg.charAt(i) == 'O'){
duration[i] = 750000;
}
else if (msg.charAt(i) == 'P'){
duration[i] = 800000;
}
else if (msg.charAt(i) == 'Q'){
duration[i] = 850000;
}
else if (msg.charAt(i) == 'R'){
duration[i] = 900000;
}
else if (msg.charAt(i) == 'S'){
duration[i] = 950000;
}
else if (msg.charAt(i) == 'T'){
duration[i] = 1000000;
}
else if (msg.charAt(i) == 'U'){
duration[i] = 1100000;
}
else if (msg.charAt(i) == 'V'){
duration[i] = 1200000;
}
else if (msg.charAt(i) == 'W'){
duration[i] = 1300000;
}
else if (msg.charAt(i) == 'X'){
duration[i] = 1400000;
}
else if (msg.charAt(i) == 'Y'){
duration[i] = 1500000;
}
else if (msg.charAt(i) == 'Z'){
duration[i] = 1600000;
}
}
}
现在,我正尝试在 Python 中做同样的事情。我对这个概念很陌生,但这是我第一次遇到这个概念的问题。
一种简单的方法是直接处理原始 PCM 数据;在这种格式中,音频数据只是一系列 -32768...32767 值,每个条目存储为 2 个字节(假设 16 位有符号,单声道),并定期采样(例如 44100Hz)。
要改变音高,您可以 "read" 更快地获取此数据,例如在 45000Hz 或 43000Hz,这很容易通过重采样程序完成。例如
import struct
data = open("pcm.raw", "rb").read()
parsed = struct.unpack("%ih" % (len(data)//2), data)
# Here parsed is an array of numbers
pos = 0.0 # position in the source file
speed = 1.0 # current read speed = original sampling speed
result = []
while pos < len(parsed)-1:
# Compute a new sample (linear interpolation)
ip = int(pos)
v = int(parsed[ip] + (pos - ip)*(parsed[ip+1] - parsed[ip]))
result.append(v)
pos += speed # Next position
speed += 0.0001 # raise the pitch
# write the result to disk
open("out.raw", "wb").write(struct.pack("%ih" % len(result)), result)
这是解决该问题的一种非常非常简单的方法,但请注意,例如增加间距会缩短长度,为了避免这种情况,需要比插值更复杂的数学运算。
例如,我使用这种方法将一首歌曲的长度提高一个音调(我想看看这是否很明显……事实并非如此)。