最近我开始修AP计算机科学。我正在做一个项目,需要两个声音文件并覆盖它们。项目本身并不是很难,我已经完成了,但我不确定我的代码是否效率低下,或者它只是在处理一个大任务。当我测试代码时,我使用了两个大小分别为390KB和1.9MB的小.wav文件。这对他们来说很好。现在我正在尝试覆盖大小分别为25.8MB和30.6MB的文件。BlueJ遇到内存错误,所以我增加了内存分配。然而,我觉得好像我的代码有问题,它运行效率低下。所以告诉我,我的代码只是承担了一个大的任务,还是有一种方法(使用提供的课程和学生的知识,大约2周的计算机科学课程和一些非正式的背景),使代码更有效?
下面是我的代码:import sounds.*;
import sounds.Sample;
import java.util.Scanner;
import java.io.*;
public class Overlay
{
public static void main(String [] args) throws IOException
{
APSoundClip clip1 = new APSoundClip("Mitch_Murder_-_Guile_39_s_Theme.wav");
APSoundClip clip2 = new APSoundClip("Darude_-_Sandstorm_80s_Version.wav");
APSoundClip greaterClip;
APSoundClip lesserClip;
if (clip1.getLength() > clip2.getLength())
{
greaterClip = clip1;
lesserClip = clip2;
}
else
{
greaterClip = clip2;
lesserClip = clip1;
}
APSoundClip clipNew = new APSoundClip(greaterClip.getLength());
Sample sampleCombo = new Sample();
System.out.println(greaterClip.getLength());
for (int i = 0; i < greaterClip.getLength() - 1; i++)
{
int val1;
int val2;
Sample sample1 = greaterClip.getSample(i);
val1 = sample1.getValue();
if (i < lesserClip.getLength())
{
Sample sample2 = lesserClip.getSample(i);
val2 = sample2.getValue();
}
else
{
val2 = 0;
}
sampleCombo.setValue(val1 + val2);
clipNew.setSample(i, sampleCombo);
}
clipNew.draw();
clipNew.play();
}
}
主要问题是你的代码需要足够的内存来容纳3个片段。而且它很可能需要更多的堆空间,因为当你必须读取/解压缩一个你不知道(未压缩)大小的数据流时,会产生开销。
不幸的是,使用APSoundClip
类,您可以做的事情不多。看来,这就是它设计的工作方式。(它的目标是易于使用来教授Java…不是世界上最有内存效率的声音处理库。)
即便如此,创建和播放输出剪辑的时间应该大致与最长的输入剪辑的长度成比例。如果您看到的时间比预期的长得多,则可能是您的堆(仍然)太小。(当堆中满是无法GC的数据时,你可能会得到一些非常糟糕的性能)
告诉我…是否有一种方法(使用所提供的课程和学生的知识,大约2周的计算机科学课程和一些非正式的背景)使代码更有效?
坦率地说,可能没有。解决方案需要:
-
扔掉你现有的代码(可能),
-
找到一个Java声音库,允许读取,处理和写入声音片段作为流;即在任何时候只在内存中保留每个片段的一小部分,并且
除非你有强烈的愿望(而且有很多时间),否则我建议你做点别的。