2015-09-09 47 views
1

最近我開始接受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(); 
    } 
} 
+0

我不認爲你的代碼是低效的,但我注意到你正在使用更大的剪輯的一個值,因爲你的計數器'i'從'0'變爲'length-2',而不是到'長度 - 1'。 –

+0

我猜測代碼中內存密集的部分超出了您向我們展示的內容,可能是您正在使用的庫函數之一。您應該使用像[Oracle Mission Control](http://www.javacodegeeks.com/2015/03/oracle-java-mission-control-the-ultimate-guide.html)這樣的分析工具,它可以幫助您找到確切的自動瓶頸。 –

+0

你把內存限制增加到了什麼程度?大概確實需要比這兩個文件稍大一些。 – immibis

回答

1

有主要問題是,你的代碼需要足夠的內存在內存中保存3個剪輯。由於當您必須讀取/解壓縮一個您不知道的(未壓縮)大小的數據流時所產生的開銷,它可能需要更多的堆空間。

不幸的是,對於使用APSoundClip的課程,您無能爲力。看起來,這是它設計的工作方式。 (其目標是易於用於教授Java ...不是世界上最具內存效率的聲音處理庫。)

即便如此,創建和播放輸出剪輯的時間應該與最長的輸入剪輯的長度。如果你看到的時間比預期長得多,那麼你的堆可能(仍然)太小。 (當堆太接近完全不能GC'ed你可以得到一些很可怕的性能數據。)


告訴我......是有辦法(使用提供課程和學生的知識,大約2周的計算機科學課程和一些非正式背景)使代碼更有效率?

坦率地說,可能沒有。該解決方案將需要:

  1. 扔掉你現有的代碼(可能),

  2. 找到一個Java的音色庫,允許讀取,處理和寫入聲音片段作爲流;即在任何一個時間只將每個片段的一小部分保存在存儲器中,並且

  3. 重寫你的代碼以使用它。

除非你有(你的手和大量的時間)的強烈願望我會建議做別的事情。

+0

OP說,這不僅僅是花時間,它還會拋出一個'StackOverflowError',即使是1個演出。即使在內存中有三個片段,內存使用量也不應超過我在此處看到的100-110MB – Dici

+0

OP沒有這麼說。他在評論中說「溢出錯誤」,但我認爲他只是意味着堆「溢出」。如果他真的意味着'StackOverflowError',那麼這個問題與堆大小無關,並且很可能是他沒有向我們顯示的代碼。例如在他沒有向我們展示的一些GUI代碼中無限遞歸。 –

+0

除了1Gb的堆溢出之外,並不合情理。不是WAV文件壓縮?我預計它們將在內存中解壓縮,並且取決於APSoundClip類如何工作,它可能需要3倍的「字數」來緩衝內存中未壓縮的剪輯。如果有人知道源代碼的位置,我們可以看看..... –

相關問題