2013-04-27 12 views
7

Bu soru StackOverflow's standartlarını geçemeyecek kadar belirsiz olabilir, ama ben seçenekleri ... dışarı çalıştırıyorum çünkü yayınlamayı deneyin zorunda:/AVAudioPlayer ve Rastgele yavaşlık

Uzun lafın kısası: Bir uygulama olduğunu rastgele yavaşlık dönemlerini yaşar. Çok sık gerçekleşmez (muhtemelen her ay bir kez), ancak olduğunda sadece iDevice üzerinde çalışan tam bir yeniden başlatma yardımcı olur. Semptomlar: 2-3 saniye yanıt süreleri ve durgun, dalgalı animasyonlar; tüm uygulama temelde kullanılamaz hale gelir.

Uygulamayı her hangi bir hata teşhis aracıyla çalıştırmıştım; bellek sızıntısı veya olağandışı yüksek CPU kullanımı yok. Ancak, bu uygulama son derece basit, bir kart oyunu için bir izci uygulaması göz önüne alındığında, şaşırtıcı değildir.

Tüm bunlar, kullanıcı button numaralı bağlantıya dokunduğunda ses çalmak için kullandığım AVAudioPlayer Bu uygulamanın nedeninin (belki de uygulamanın tamamında göreceli olarak yüksek karmaşıklık unsuru) olabileceğine inanmamı sağladı. Ancak, emin değilim, nerede yardıma ihtiyacım var. Burada örnek bir kod ekledim ve belki de iOS ses çalma deneyimine sahip biri bunu gözden geçirebilir ve gözden kaçırdığım bir hata olup olmadığını görebilir.

İşte biz: İlk olarak, AVAudioPlayer'u canlı tutmak için her saniyede sessiz bir parça çalmaya devam eden bir "sessiz oyuncu" başlatıyorum. Daha uzun bir hareketsizlik süresinden sonra çağrıldığında görece uzun yanıt süresi AVAudioPlayer deneyimleri nedeniyle gereklidir.

- (void) repeatSilence 
{ 
    if (isAudioON == YES) 
    { 
     if (silencePlayer.playing) 
     { 
      [silencePlayer stop]; 
      silencePlayer.currentTime = 0; 
      [silencePlayer play]; 
     } 
     else 
     { 
      [silencePlayer play]; 
     } 
    } 
} 

gerisi oldukça basittir:

NSString *silenceFilePath = [[NSBundle mainBundle] pathForResource: @"silence" ofType: @"wav"]; 
NSURL *silenceFileURL = [[NSURL alloc] initFileURLWithPath: silenceFilePath]; 
silencePlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: silenceFileURL error: nil]; 
[silencePlayer setDelegate: self]; 
[silencePlayer prepareToPlay]; 

silenceTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f 
               target:self 
               selector:@selector(repeatSilence) 
               userInfo:nil 
               repeats:YES]; 

NSTimer şu yöntemi çağırır.

NSString *buttonSoundFilePath = [[NSBundle mainBundle] pathForResource: @"button_pushed" ofType: @"wav"]; 
NSURL *buttonFileURL = [[NSURL alloc] initFileURLWithPath: buttonSoundFilePath]; 
buttonPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: buttonFileURL error: nil]; 
[buttonPlayer setDelegate: self]; 
[buttonPlayer prepareToPlay]; 

Ve düğmesine basıldığında (Sessiz oyuncuyla yaptığı gibi aynı şekilde) Ben ses çalma: Ben (bunlardan iki tane vardır) Belirli düğme sesi çalmak için başka AVAudioPlayer başlatmak

if (isAudioON == YES) 
{ 
    if (buttonPlayer.playing) 
    { 
     [buttonPlayer stop]; 
     buttonPlayer.currentTime = 0; 
     [buttonPlayer play]; 
    } 
    else 
    { 
     [buttonPlayer play]; 
    } 
} 

Ve gerçekten hepsi bunun için var. Bununla birlikte, korkarım ki, bu yöntemin basit doğasına rağmen, bir şekilde bu sürekli ses çalma, iOS'un çıldırdığı nadir bir örnek oluşturur. Ama bütün bunlar sadece bir teori, ve bu yüzden koduma bir göz atmak ve görüşlerini paylaşmak için daha fazla deneyime sahip birine ihtiyacım var.

Teşekkürler!

Güncelleştirme: Sorunla ilgili olabilecek başka bir kod satırı da buldum. Onlarla birlikte, ben AVAudioPlayer müzik (örneğin başka bir uygulamanın) arka planda çalmaya ile eş zamanlı çalışmak ayarlayın:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; 
[[AVAudioSession sharedInstance] setActive:YES error:nil]; 
[[AVAudioSession sharedInstance] setDelegate:self]; 

cevap

1

Ne Yukarıdaki koddan gözlemlemek, iki değişiklikleri önermek istiyorum.

1) İki saniyede sürekli sessiz ses çalmak için AVAudioPlayer örnekleri kullandınız. AVAudioPlayer uygulamasının ikinci bir örneği, düğmeye basıldığında sesi çalmak içindir.Aynı anda iki örnekte AVAudioPlayer'ın çalıştırılması, cihazda bellek düşük olduğunda ve sessiz ses ve düğme sesinin aynı anda çalınması gerektiğinde, cihaz yavaş çalışacaktır. Her iki sesi de oynatmak için bir AVAudioPlayer örneğini kullanmak daha iyidir.

2) Kullanıcı, düğmeye basana kadar sessiz sesi çalmaya devam edin. Kullanıcı düğmeyi tıkladığında, zamanlayıcıyı duraklatın ve mevcut sesi durdurun ve aynı AVAudioPlayer örneğini kullanarak düğme sesini çalın. Bu şekilde, tavsiye edilmeyen zamanlayıcı, düğme sesinin çalınması gerektiğinde bir süre için durdurulacaktır, düğmenin sesi bittiğinde çalma, aynı sesi AVAudioPlayer örneğiyle aynı ses çalmak için zamanlayıcıyı sürdürecektir. Bu, bellek ve işlemeden çok fazla yük alacaktır.

+0

İyi analizlere ulaşın. Bu haftasonu deneyecek ve sonuçları paylaşacağım! –

4

Sorunuzdan derlediklerimden, oynamak istediğiniz tek seslerin nispeten basit ve kısa ses efektleri olduğu görülüyor. Bu durumda, sabit bir ses düzeyinde ses efektleri çalmak kadar basit bir şey için bir kaynak ağır kütüphanesi olduğu için, AVAudioPlayer kullanmazdım. Doğrudan Ses Hizmetlerini kullanırdım. İşte başka bir yerden çektiğim bir Ses Efekt Sınıfı örneği (artık nerede olduğunu hatırlayamıyorum).

SoundEffect.h

#import <Foundation/Foundation.h> 
#import <AudioToolbox/AudioToolbox.h> 

@interface SoundEffect : NSObject 
{ 
    SystemSoundID soundID; 
} 

- (id)initWithSoundNamed:(NSString *)filename; 
- (void)play; 

@end 

Eğer bu sınıfı sahip olduktan sonra, kolayca aşağıdaki kodu kullanarak herhangi bir ses efekti oynayabilirsiniz

#import "SoundEffect.h" 

@implementation SoundEffect 

- (id)initWithSoundNamed:(NSString *)filename 
{ 
    if ((self = [super init])) 
    { 
     NSURL *fileURL = [[NSBundle mainBundle] URLForResource:filename withExtension:nil]; 
     if (fileURL != nil) 
     { 
      SystemSoundID theSoundID; 
      OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef)fileURL, &theSoundID); 
      if (error == kAudioServicesNoError) 
       soundID = theSoundID; 
     } 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    AudioServicesDisposeSystemSoundID(soundID); 
} 

- (void)play 
{ 
    AudioServicesPlaySystemSound(soundID); 
} 

@end 

SoundEffect.m:

SoundEffect *mySoundEffect = [[SoundEffect alloc] initWithSoundNamed:@"mySound.wav"]; 
[shareSoundEffect play]; 

Optimizasyon için, tüm ses efektlerinizi bir yere yükler ve statik olarak depolar, böylece gerçek ses dosyalar önceden yüklenir, daha sonra onlara ihtiyaç duyduğunuzda sadece "oynat" komutunu çağır. Bunu yapmak, AVAudioPlayer'ı kullanmadan ses efektlerini oynatmanın çok daha az kaynak ağır yoludur. Kim bilir, belki sorununuzu çözecektir. Bunun ne kast

bu sesler daha basittir: ses dosyasını Preloading

. Ben sadece program ilk yüklendiğinde onları başlattıktan sonra her Sound Effect nesnesine statik bir referans oluşturacağınız anlamına gelir. Bunu yapmanın birkaç yolu var. Genellikle + load metodunu kullanırım. Böyle bir şey olacaktır:

, SoundEffect sınıfının

static SoundEffect *mySoundEffect; 

Sonraki uygulanmasında statik değişkeni ekleyin Sound Effect sınıf için + yük yönteminde değişkene başlangıç.

+(void)load 
{ 
    mySoundEffect = [[SoundEffect alloc] initWithSoundNamed:@"mySound.wav"]; 
} 

Şimdi sadece bu gibi ses efekti sınıf için statik bir yöntem oluşturun: arayarak

+(void)playMySound 
{ 
    [mySoundEffect play]; 
} 

Bundan sonra, sadece herhangi bir zamanda bu ses çalabilir:

[SoundEffect playMySound]; 

ses kontrolleri hakkında bir not:

benim IOS uygulamaları birçok bu kodu kullanıyorum ve followi teyit edebilir ng:

  1. Aygıtın yan tarafındaki standart ses denetimleri normal olarak çalışır, ancak yalnızca kullanıcının ayarları, zil seslerinin ve uyarıların düğmelerle değiştirilebileceğini belirtirse çalışacaktır.
  2. Kodunuzdaki sesin sesini denetlemenin bir yolu yoktur.
+0

Kesinlikle bunu deneyeceğim. Ancak, kodunuzdaki SystemSoundID değişkenini fark ettim. Bu, yönteminizin sesleri çalmak için sistem ses nesnesini kullandığı anlamına mı geliyor? Eğer durum buysa, sistem seslerini kullanırken problemim değer kontrolü eksikliğidir. Onları denedim. Ayrıca, ses dosyalarını "önyükleme" nasıl bir örnek verebilir misiniz? Bu uygulamaya aşina değilim. –

+0

Bu doğru, bu durumda ses efektinin sesini programlı olarak kontrol edemeyeceksiniz. Daha düşük veya daha yüksek bir ses seviyesinde ses efektine ihtiyacınız varsa, daha düşük ve daha yüksek ses düzeylerinde ses dosyasının farklı sürümlerine sahip olmanız gerekir. Ses efektinin hacminin üzerinde dinamik kontrole sahip olmanız gerekiyorsa, maalesef bu çözüm sizin için uygun olmayabilir. :( – csundman

+0

Ben programlanabilir denetime ihtiyacı yok ses efektleri – csundman