2013-09-25 30 views
13

Tôi đang phát triển trò chơi trong Android và tôi gặp phải một lỗi rất khó chịu, khó tìm. Vấn đề là khi bạn đang sử dụng SoundPool để phát âm thanh của mình, bạn thực sự có thể lặp lại bất kỳ âm thanh nào bạn đang phát. Trong trường hợp này, vấn đề là âm thanh "bước chạy"; âm thanh này được thực hiện khá nhanh và liên tục (xung quanh mỗi 400ms) khi nhân vật chính đang chạy.Cách phát âm thanh vào các khoảng thời gian chính xác trên các thiết bị khác nhau trong Android

Bây giờ, khi phát âm thanh trên thiết bị thông thường (không quá mạnh), ví dụ: Samsung SII, âm thanh được phát mỗi 500ms - tuy nhiên, nếu tôi chạy cùng một mã trên một thiết bị khác (giả sử, Samsung SIV, Samsung SIII), âm thanh phát nhanh gấp hai lần hoặc thậm chí ba lần.

Dường như thông số kỹ thuật phần cứng thiết bị càng mạnh, tốc độ phát càng nhanh. Trên một số thiết bị, nó phát nhanh đến nỗi bạn gần như nghe thấy một âm thanh liên tục chắc chắn. Tôi đã tìm kiếm các kỹ thuật để thiết lập một tỷ lệ cụ thể trong khoảng thời gian giữa các lần phát âm thanh, nhưng nó không hoạt động đúng và vấn đề vẫn còn. Có ai biết cách sửa chữa nó, hoặc sử dụng SoundPool, MediaPlayer hoặc bất kỳ API kiểm soát âm thanh nào khác trên Android không?

+0

bạn có tìm thấy giải pháp không? Nếu vậy hãy chia sẻ nó!! – lelloman

+0

Bạn vẫn chưa tìm kiếm nó, nếu bạn +1 câu hỏi, có thể nhiều người sẽ chú ý vào nó ... –

+1

Tôi không thể upvote nhiều hơn một lần – lelloman

Trả lời

0

Bạn có thể sử dụng AudioTrack để phát luồng dữ liệu PCM liên tục, vì bạn sẽ chuyển luồng, bạn có thể chắc chắn về khoảng thời gian giữa các âm thanh. Nhược điểm có thể là một chút chậm trễ khi lần đầu tiên bắt đầu âm thanh nhưng nó phụ thuộc vào kích thước bộ đệm tối thiểu, và nó phụ thuộc, tôi nghĩ rằng, trên phiên bản Android và thiết bị. Trên thiên hà của tôi android android 4.1 là khoảng 20ms.
nếu bạn nghĩ rằng đây có thể là một tùy chọn tôi có thể đăng một số mã số

1

Sự cố chỉ lặp lại hoặc sử dụng khoảng thời gian thường xuyên cho bước như bước chân là bạn có thể tách âm thanh và hình ảnh. Nếu âm thanh của bạn bị trễ hoặc tăng tốc hoặc hình ảnh của bạn bị trì hoãn hoặc tăng tốc, bạn sẽ phải điều chỉnh độ trễ đó một cách tự động và tự động. Bạn đã có vấn đề ngay tại đây

Giải pháp tốt hơn là đặt trình kích hoạt vào sự kiện chính xác sẽ kích hoạt âm thanh (trong trường hợp này, bàn chân được đặt xuống), sau đó phát âm thanh. Điều này cũng có nghĩa là nếu bạn có nhiều nguồn âm thanh (như nhiều bước chân), bạn không phải tự khởi động âm thanh với khoảng thời gian phù hợp.

+0

Cách tiếp cận này có một khoảng cách rất lớn, vì không phải tất cả các trường hợp có thể đếm với một sự kiện mỗi khi tôi muốn một âm thanh "ví dụ như một khẩu súng authomatic", là một sự kiện duy nhất để kích hoạt, và âm thanh phải lặp tại thời gian cụ thể interevals cho đến khi ngón tay được phát hành từ ... –

+0

Nếu bạn có một âm thanh súng tự động, một vòng lặp là tốt hơn, có, nhưng trừ khi bạn làm một trò chơi autorunner hoặc một trò chơi phiêu lưu phong cách Myst, lặp lại âm thanh là một ý tưởng tồi. Tốt hơn là nên liên kết nó với bước chân, bởi vì cách đó âm thanh luôn đi đôi với bước chân. Tôi đã không nói để lặp lại nó tất cả các thời gian. – Nzall

0

Tôi dường như không thể sao chép sự cố trên Galaxy Nexus và Nexus S, điều đó có nghĩa là tôi đã khắc phục sự cố không? Hoặc có thể bạn có thể hiển thị những gì bạn đang làm cách khác nhau từ này:

SoundPool soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100); 
Integer sound1 = soundPool.load(this, R.raw.file1, 1); 
Integer sound2 = soundPool.load(this, R.raw.file2, 1); 
playSound(sound1); 

public void playSound(int sound) { 
    AudioManager mgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
    float volume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC) 
      /mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC); 
    soundPool.play(sound, volume, volume, 1, -1, 1.0f); 
} 
+0

Không có gì, tôi làm chính xác điều đó, thử nghiệm với một thiết bị cũ, và bạn sẽ nhận thấy sự khác biệt lớn về khoảng cách giữa một âm thanh và âm thanh tiếp theo, nó sẽ có độ trễ lớn hơn giữa nhau, đó chính xác là mã tôi có ... –

0

Nếu vấn đề là bạn muốn kiểm soát khoảng cách giữa những âm thanh rời rạc, Cách dễ nhất để làm điều này là với một handler.

Về cơ bản, bạn bắt đầu phát âm thanh là quá trình không đồng bộ. Sau đó, bạn sử dụng một trình xử lý để lên lịch một tin nhắn để phát âm thanh tiếp theo trong tương lai. Nó sẽ mất một số thử nghiệm và lỗi để làm cho nó đúng, nhưng bạn sẽ được đảm bảo rằng âm thanh sẽ bắt đầu tại cùng một khoảng thời gian sau khi âm thanh trước đó trên mọi thiết bị.

Dưới đây là một số mã để minh họa những gì tôi đang nói đến.

Dưới đây là một việc thực hiện xử lý bạn có thể sử dụng:

handler = new Handler() { 

     /* (non-Javadoc) 
     * @see android.os.Handler#handleMessage(android.os.Message) 
     */ 
     @Override 
     public void handleMessage(Message msg) { 
      if (msg.what == NEXT_ITEM_MSG) { 
       playNextSound(); 
      } 
      else if (msg.what == SEQUENCE_COMPLETE_MSG) { 
       // notify a listener 
       listener.onSoundComplete() 
      } 
     } 
    }; 

Sau đó, bạn có thể viết playNextSound như thế này:

private void playNextSound() { 
    if (mRunning) { 
     // Get the first item 
     SoundSequenceItem item = currentSequence.getNextSequenceItem(); 
     if (item == null) { 
      Message msg = handler.obtainMessage(SEQUENCE_COMPLETE_MSG); 
      handler.sendMessage(msg); 
      return; 
     } 
     // Play the sound 
     int iSoundResId = item.getSoundResId(); 
     if (iSoundResId != -1) { 
      player.playSoundNow(soundResId); 
     } 

     // schedule a message to advance to next item after duration 
     Message msg = handler.obtainMessage(NEXT_ITEM_MSG); 
     handler.sendMessageDelayed(msg, item.getDuration()); 
    } 
} 

và SoundSequenceItem bạn chỉ có thể là một lớp đơn giản mà có một nguồn tập tin âm thanh id và thời lượng. Nếu bạn muốn tiếp tục phát âm thanh trong khi nhân vật đang di chuyển, bạn có thể làm điều gì đó như sau:

public void onSoundComplete() { 
    if (character.isRunning()) { 
     currentSequence.addSequenceItem(new SoundSequenceItem(R.id.footsteps,500); 
     playNextSound(); 
    } 
} 

Hoặc bạn có thể sửa đổi playNextSound để tiếp tục phát âm thanh tương tự. Của tôi được viết theo cách này để có thể chơi các âm thanh khác nhau theo thứ tự.

+0

Tôi đã nghĩ về một số cách để thực hiện thủ công, như ThreadPools/Scheduler/Monitor và thậm chí cả trình xử lý, tuy nhiên tôi đang tìm kiếm một cuộc gọi gốc làm câu trả lời, thực hiện theo cách thủ công sẽ không thành vấn đề chỉ tìm kiếm thứ gì đó hiện có trong API –

0

Tôi đã gặp nhiều sự cố khi phát triển các ứng dụng sử dụng âm thanh và nội dung như vậy. Tôi sẽ không đề nghị bạn sử dụng SoundPool vì nó bị ảnh hưởng bởi lỗi và cũng lưu ý rằng việc lặp lại âm thanh với SoundPool sẽ không hoạt động trên các thiết bị từ 4.3 trở lên, xem this open issue, at AOSP - Issue tracker. Tôi nghĩ rằng giải pháp là để đi bản địa và sử dụng OpenSL ES o thư viện tương tự.