问题:

在pyworld使用前,一般需要读取音频文件:

  • librosa.load() 默认得到的是float32类型的数据,所以一般会再跟上 x.astype(np.float64)

    • 而恰恰是这么一个Numpy类型转换,会导致得到的 ap 特征中会含有 Nan 数据,这会导致最终的计算出现不必要的偏差;
1
2
3
4
5
6
7
print(f"ap {np.isnan(ap).any()}")  # 返回True

#统计nan个数
t = ap
t = t[np.isnan(t)] # 用切片法 + 条件限制,来得到 nan 值的切片
# t = t[np.where(np.isnan(t))]
print(t.shape) # (4k+, )
  • (这个问题和怎么计算得到ap无关:尝试了 world.wav2worl()和 pyworld.harvest + cheaptrick + d4c路径,结果都一样)

  • Soundfile.read() # 默认的数据返回值是 float64,所以可以直接得到所要求的数据格式

  • 其中,对应的函数参数调整:sr 变为 samplerate , mono 的单通道 改用 channels=1

Ps.附上代码和 issue网址

[issue][https://github.com/JeremyCCHsu/Python-Wrapper-for-World-Vocoder/issues/50]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import numpy as np
import pyworld as world
import pyworld
import librosa
import librosa.display
import os
import soundfile

# wav,fs = librosa.load(os.getcwd()+"/bed (537).wav")
wav, fs = soundfile.read(os.getcwd()+"/bed (537).wav")
# wav = wav.astype(np.float64)
# print(wav[0].type) # 'numpy.float64' object has no attribute 'type'
frame_period = 5.0
hop_length = int(fs * frame_period * 0.001)
fftlen = world.get_cheaptrick_fft_size(fs)

f0, timeaxis = pyworld.harvest(wav, fs, frame_period=frame_period, f0_floor=71.0, f0_ceil=800.0)
sp = pyworld.cheaptrick(wav, f0, timeaxis, fs)
ap = pyworld.d4c(wav, f0, timeaxis, fs)

# f0, sp, ap = world.wav2world(x,sr,fftlen,frame_period)
print(ap.shape)
print(f"ap {np.isnan(ap).any()}")

wav = pyworld.synthesize(f0, sp, ap, fs, frame_period)
# wav = wav.astype(np.float32)
soundfile.write('test.wav', wav, fs)

x, sr = soundfile.read(os.getcwd()+"/bed (537).wav")
# print(x[0].type) # 'numpy.float64' object has no attribute 'type'
f01, timeaxis1 = pyworld.harvest(x, sr, frame_period=frame_period, f0_floor=71.0, f0_ceil=800.0)
sp1 = pyworld.cheaptrick(x, f01, timeaxis1, fs)
ap1 = pyworld.d4c(x, f01, timeaxis1, fs)

'''
以上这样,直接用soundfile 读取成float64 数据,
然后再直接用 soundfile.write 保存float64的文件 或者是 先转化成float32 再保存成文件,
保存出来的文件再次用soundfile 读取出来,
再次用测试ap是否有 nan值,都没有问题。
综上,能用soundfile就避免用librosa,读取和写入文件都是这个道理;ßå
'''

print('************')
print(ap1.shape)
print(f"ap1 {np.isnan(ap1).any()}")

print(f"ap {np.isnan(ap).any()}")

# # print(np.isnan(ap))
# t = ap
# t = t[np.isnan(t)]
# # t = t[np.where(np.isnan(t))]
# print(t.shape)

count = 0
for x in ap:
# if np.isnan(x):
count = count+1

print(count)

if np.isnan(ap).any():

f0, sp, ap = world.wav2world(np.absolute(x),fs,fftlen,frame_period)
print(f"ap abs {np.isnan(ap).any()}")

exit()

参考:

  1. https://github.com/mmorise/World/issues/90 (有人提问 WORLD 提取得到的 mel spectrum 梅尔谱和传统概念上 经过一系列stft之后还要经过“三角滤波器组”的过程区别?)
  2. https://github.com/mmorise/World/issues/33 (r9y9 在mmorise/World 下提问关于 编码/解码后音色变化问题;代码bug已解决;学习一下画图和使用特点)

阅读全文 »

1.解题思路:

  • 动态规划听上去非常高大上,但是其实都是源自于一个很自然的想法,就拿这道题来说,假如需要判断”onetwothreefour”这一个字符串能不能满足条件,我们很自然的想法就是:
  • 如果”onetwothree”这一段可以拆分,再加上four如果也可以,那不就行了;
  • 或者
  • 如果”onetwothre”这一段可以拆分,再加上efour如果也可以,那不就行了;
  • 这其实已经抓住了动态规划的最核心的东西了,换成式子来表达,就是
1
2
dp["onetwothreefour"] = dp["onetwothree"这一段] && 判断一下"four"
dp["onetwothreefour"] = dp["onetwothre"这一段] && 判断一下"efour"

2.代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.util.*;

public class 单词拆分_139 {
public static void main(String[] args) {
}
public Map<String, Boolean> map = new HashMap<>();
public boolean wordBreak(String s, List<String> wordDict){

boolean[] dp = new boolean[s.length() + 1];
//Java boolean数组默认值为False

//将List中单词放进 HashMap
for(String word:wordDict){
map.put(word, true);
}

//初始化
dp[0] = true;

//遍历
/*
* public String substring(int beginIndex, int endIndex)
* beginIndex -- 起始索引(包括), 索引从 0 开始
* endIndex -- 结束索引(不包括)
* 索引:读取数组时的下标
* */
for(int i=1;i<s.length();i++){
for(int j=i-1;j>=0;j--){
dp[i] = dp[j] && check(s.substring(j, i));
if(dp[i]) break;//这句也很精髓
}
}
return dp[s.length()];
}
public boolean check(String s){
return map.getOrDefault(s, false);
}
}

3.Refrence