Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 改变波表节距(重采样)_Java_Math_Audio - Fatal编程技术网

Java 改变波表节距(重采样)

Java 改变波表节距(重采样),java,math,audio,Java,Math,Audio,我一直在用数学方程式为android做一些基本的合成。问题在于,这些公式一直在变得越来越复杂。所以我开始使用波表合成 到目前为止,我可以根据字节数组和预定频率播放单个音符。然而,当寻找公式来重新采样样本和改变波表的间距。。。我就是找不到一个简单的解决办法。整个图书馆都在这样做。但感觉应该是一个简单的公式,通过下采样或过采样来改变采样频率 有没有简单的方法 例如:输入是[0,0.5,1,0.5,0…]让我们假设它是C4 要使其成为C3,预期输出应为[0,0.25,0.5,0.75,1,0.75,0

我一直在用数学方程式为android做一些基本的合成。问题在于,这些公式一直在变得越来越复杂。所以我开始使用波表合成

到目前为止,我可以根据字节数组和预定频率播放单个音符。然而,当寻找公式来重新采样样本和改变波表的间距。。。我就是找不到一个简单的解决办法。整个图书馆都在这样做。但感觉应该是一个简单的公式,通过下采样或过采样来改变采样频率

有没有简单的方法

例如:输入是
[0,0.5,1,0.5,0…]
让我们假设它是C4

要使其成为C3,预期输出应为
[0,0.25,0.5,0.75,1,0.75,0.5,0.25,0…]

基本上,它是和安卓的音频池“速率”属性,但只是对字节进行重采样的公式,我在任何地方都找不到

编辑:

感谢菲尔·弗雷霍夫指导我找到答案。然而,他提供的原始公式并没有在过采样的情况下平滑末端。但这是一个非常好的开始,我只需要顺利结束。我将附上我的最终代码,以防有人想要一个简单的函数来“扩展”浮点数组

public static void main(String[] args) {
        float[] sample = {0f, 0.5f, 1f, 0.5f, 0f, 0.5f, 1f, 0.5f, 0};

        System.out.println(Arrays.toString(resample(sample, 2f)));
        //[0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.125, 0.0]
        System.out.println(Arrays.toString(resample(sample, 3f)));
        //[0.0, 0.16666667, 0.33333334, 0.5, 0.6666667, 0.8333333, 1.0, 0.8333334, 0.6666666, 0.5, 0.33333337, 0.16666663, 0.0, 0.16666675, 0.33333325, 0.5, 0.66666675, 0.83333325, 1.0, 0.83333325, 0.66666675, 0.5, 0.33333325, 0.16666675, 0.111111164, 0.055555582, 0.0]
        System.out.println(Arrays.toString(resample(sample, 0.5f)));
        //[0.0, 1.0, 0.0, 1.0, 0.0]
        System.out.println(Arrays.toString(resample(sample, 1f)));
        //[0.0, 0.5, 1.0, 0.5, 0.0, 0.5, 1.0, 0.5, 0.0]
        System.out.println(Arrays.toString(resample(sample, 4.3f)));
        //[0.0, 0.116279066, 0.23255813, 0.3488372, 0.46511626, 0.5813953, 0.6976744, 0.81395346, 0.9302325, 0.95348847, 0.83720934, 0.72093034, 0.6046512, 0.4883722, 0.37209308, 0.25581408, 0.13953495, 0.023255944, 0.09302306, 0.20930219, 0.3255813, 0.44186044, 0.5581393, 0.67441845, 0.7906976, 0.9069767, 0.9767444, 0.8604653, 0.74418616, 0.62790704, 0.51162815, 0.39534903, 0.2790699, 0.16279078, 0.04651189, 0.034883916, 0.023255944, 0.011627972, 0.0]
    }

    public static float[] resample(float[] sample, float rate) {
        if (rate == 1) {
            return sample;
        }
        int newLength = Math.round(sample.length * rate); 
        int rateUnit = (int) Math.round(rate);
        float[] result = new float[newLength];
        for (int i = 0; i < newLength - rateUnit; i++) {
            float val = (i / rate);
            int o = (int) val;
            result[i] = sample[o + 1] * (val - o)
                    + sample[o] * ((o + 1) - val);
        }
        int startIndex = newLength - rateUnit;

        for (int u = 0; u < newLength - startIndex; u++) {
            result[startIndex + u] = result[startIndex - 1] + (u + 1) * 
                    (sample[sample.length - 1] - result[startIndex - 1]) / rateUnit;
        }
        return result;
    }
publicstaticvoidmain(字符串[]args){
浮动[]样本={0f,0.5f,1f,0.5f,0f,0.5f,1f,0.5f,0};
System.out.println(Arrays.toString(重采样(sample,2f));
//[0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.125, 0.0]
System.out.println(Arrays.toString(重采样(sample,3f));
//[0.0, 0.16666667, 0.33333334, 0.5, 0.6666667, 0.8333333, 1.0, 0.8333334, 0.6666666, 0.5, 0.33333337, 0.16666663, 0.0, 0.16666675, 0.33333325, 0.5, 0.66666675, 0.83333325, 1.0, 0.83333325, 0.66666675, 0.5, 0.33333325, 0.16666675, 0.111111164, 0.055555582, 0.0]
System.out.println(Arrays.toString(重采样(采样,0.5f));
//[0.0, 1.0, 0.0, 1.0, 0.0]
System.out.println(Arrays.toString(重采样(sample,1f));
//[0.0, 0.5, 1.0, 0.5, 0.0, 0.5, 1.0, 0.5, 0.0]
System.out.println(Arrays.toString(重采样(样本,4.3f));
//[0.0, 0.116279066, 0.23255813, 0.3488372, 0.46511626, 0.5813953, 0.6976744, 0.81395346, 0.9302325, 0.95348847, 0.83720934, 0.72093034, 0.6046512, 0.4883722, 0.37209308, 0.25581408, 0.13953495, 0.023255944, 0.09302306, 0.20930219, 0.3255813, 0.44186044, 0.5581393, 0.67441845, 0.7906976, 0.9069767, 0.9767444, 0.8604653, 0.74418616, 0.62790704, 0.51162815, 0.39534903, 0.2790699, 0.16279078, 0.04651189, 0.034883916, 0.023255944, 0.011627972, 0.0]
}
公共静态浮点[]重采样(浮点[]采样,浮点率){
如果(比率==1){
返回样品;
}
int newLength=Math.round(sample.length*rate);
整数比率单位=(整数)数学四舍五入(比率);
float[]结果=新的float[newLength];
对于(int i=0;i
假设您有一个浮动波形表

然后,您可以创建一个“游标”在表格中进行迭代。该游标不必是整数,它可以是浮点。当光标落在波形表两个元素之间的值上时,您可以使用线性插值计算“足够好”的返回值

以第一个波形表为例。当使用增量为1的光标时,它会播放C4。如果将增量设置为0.5并使用线性插值,则返回的值将与低于八度的表格内容相同

但您可以选择任何增量值,甚至可以随时间改变它(以获得glissandos)

光标增量的确切大小取决于波形表的大小、采样率以及所需的螺距

我正在为我编码的FM合成器使用波形表。正弦波表对于单波、浮点分辨率有1024个增量。它似乎工作得很好。声音非常清晰——绝对比我使用旧雅马哈DX7或第二代DX7时得到的量化噪声要少

以下是我当前使用的代码,用于使用线性插值返回给定光标值的波形表值:

public static float get(float i)
{
    final int idx = (int)i;
    
    return data[idx + 1] * (i - idx) 
            + data[idx] * ((idx + 1) - i);
}

数据表是长度为1025的
float[]
,而周期为1024步。我有
data[0]==data[1024]
因此,上述算法适用于范围
0内的任何光标值。感谢您的代码。让它工作起来真的很有用;)而且它也可以用javascript实现,这对跨平台来说是一个巨大的优势。很高兴能帮上忙!如果您在javascript中得到一些东西,我很有兴趣看到/听到它。我想我用Java所做的音频编码更直接地在web上老化。