البداية البطيئة ل Avaudioplayer في المرة الأولى التي يتم فيها تشغيل الصوت

StackOverflow https://stackoverflow.com/questions/900461

سؤال

أحاول القضاء على تأخر بدء التشغيل عند تشغيل ملف صوتي (قصير للغاية - أقل من ثانيتين) عبر Avaudioplayer على iPhone.

أولا، الرمز:

NSString *audioFile = [NSString stringWithFormat:@"%@/%@.caf", [[NSBundle mainBundle] resourcePath], @"audiofile"];
NSData *audioData = [NSData dataWithContentsOfMappedFile:audioFile];

NSError *err;
AVAudioPlayer *audioPlayer = [(AVAudioPlayer*)[AVAudioPlayer alloc] initWithData:audioData error:&err];

audioPlayer.delegate = self;
[audioPlayer play];

أقوم أيضا بتطبيق طريقة Audioplayerdididfinishplaying لإصدار Avaudioplayer بمجرد الانتهاء.

في المرة الأولى التي ألعب فيها الصوت، يكون التأخر واضحا - 2 ثانية على الأقل. ومع ذلك، بعد أن يلعب الصوت على الفور. أظن أن الجاني، ثم، هو [NSDATA DATAWITHONTSOFMAPTFILE] يستغرق وقتا طويلا في القراءة من الفلاش في البداية، ولكن بعد ذلك بسرعة قراءات في وقت لاحق. لست متأكدا من اختبار ذلك، رغم ذلك.

هل هذا هو الحال؟ إذا كان الأمر كذلك، هل يجب علي مجرد التخزين المؤقت كائنات NSDATA وتكون عدوانية حول تطهيرها في ظروف الذاكرة المنخفضة؟

هل كانت مفيدة؟

المحلول

يبدو أن التأخير مرتبط بميزة Avaudioplayer لأول مرة. إذا قمت بتحميل أي صوت، قم بتشغيل [EudioPlayer EppedEtoplay] ثم حررها على الفور، أوقات الحمل لجميع صوتي آخر قريب جدا من غير محسوس. حتى الآن أنا أفعل ذلك في ApplicationDiddfinishLaunching وكل شيء آخر يعمل بشكل جيد.

لا يمكنني العثور على أي شيء حيال ذلك في المستندات، ولكن بالتأكيد يبدو أنه هو الحال.

نصائح أخرى

إليك ما قمت به (في مؤشر ترابط منفصل):

[audioplayer start]
[audioplayer stop]
self.audioplayer = audioplayer

AudiOplayer EppedEtoplay] يبدو أنه طريقة غير متزامنة، لذلك لا يمكنك التأكد من إرجاعها إذا كان الصوت في الواقع جاهز للعب.

في حالتي، اتصلت البدء في بدء اللعب فعليا - يبدو أن هذا متزامن. ثم أوقفها على الفور. في المحاكي على أي حال، لا أسمع أي صوت يخرج من هذا النشاط. الآن بعد أن يكون الصوت "حقا" جاهزا للعب، أقوم بتعيين المتغير المحلي لمتغير العضو حتى رمز الخيط لديه حق الوصول إليه.

يجب أن أقول أنني أجد أنه من المستغرب إلى حد ما أنه حتى على iOS 4 يستغرق حوالي 2 ثانية فقط لتحميل ملف صوتي يبلغ طوله 4 ثوان فقط ....

إذا كان طول الصوت أقل من 30 ثانية، فستكون في تنسيق PCM أو IMA4 الخطي، ويتم تعبئته كأداة .caf، أو .wav، أو .aiff، يمكنك استخدام أصوات النظام:

استيراد إطار AudiOtoolbox

في ملف .h الخاص بك إنشاء هذا المتغير:

SystemSoundID mySound;

في ملف .m الخاص بك تطبيقه في طريقة التابعة الخاصة بك:

-(id)init{
if (self) {
    //Get path of VICTORY.WAV <-- the sound file in your bundle
    NSString* soundPath = [[NSBundle mainBundle] pathForResource:@"VICTORY" ofType:@"WAV"];
    //If the file is in the bundle
    if (soundPath) {
        //Create a file URL with this path
        NSURL* soundURL = [NSURL fileURLWithPath:soundPath];

        //Register sound file located at that URL as a system sound
        OSStatus err = AudioServicesCreateSystemSoundID((CFURLRef)soundURL, &mySound);

            if (err != kAudioServicesNoError) {
                NSLog(@"Could not load %@, error code: %ld", soundURL, err);
            }
        }
    }
return self;
}

في طريقة iBaction الخاصة بك تسميه الصوت مع هذا:

AudioServicesPlaySystemSound(mySound);

يعمل هذا بالنسبة لي، تشغيل الصوت لعنة جميلة بالقرب من عند الضغط على الزر. آمل أن يساعدك هذا.

لقد اتخذت نهجا بديلا يعمل بالنسبة لي. لقد رأيت هذه التقنية المذكورة في مكان آخر (ثو لا أتذكر في الوقت الحالي حيث كان ذلك).

باختصار، اختبرت نظام الصوت عن طريق التحميل ولعب صوت قصير "فارغ" قبل أن تفعل أي شيء آخر. يشبه الرمز مثل هذا لملف MP3 قصير التحميل في التحميل في رأييviewDidLoad الطريقة التي من .1 ثانية المدة:

   NSError* error = nil;
   NSString* soundfilePath = [[NSBundle mainBundle] pathForResource:@"point1sec" ofType:@"mp3"];
   NSURL* soundfileURL = [NSURL fileURLWithPath:soundfilePath];
   AVAudioPlayer* player = [[[AVAudioPlayer alloc] initWithContentsOfURL:soundfileURL error:&error] autorelease];
   [player play];  

يمكنك إنشاء MP3 فارغة الخاصة بك إذا كنت تريد، أو قم بعمل بحث Google على "ملفات MP3 فارغة" للعثور على واحد وتنزيله بالفعل من قبل شخص آخر.

كتبت غلاف بسيط ل Avaudioplayer الذي يوفر طريقة تحضيرية يعمل فعلا:

https://github.com/nicklockwood/SoundManager.

إنه في الأساس يقوم فقط بمسح تطبيقك لملفات الصوت، يختار واحدا ويلعبه عند مستوى صوت صفر. التي تتم تهيئة أجهزة الصوت وتسمح الصوت التالي باللعب على الفور.

الحل البديل الآخر هو إنشاء صوت قصير وصامف وتشغيله في أول مرة يتم تشغيل اللاعب.

  1. اضبط مستوى الميكروفون على 0 على تفضيلات النظام.
  2. فتح Quicktime.
  3. إنشاء تسجيل صوتي جديد (ملف> تسجيل صوت جديد).
  4. سجل لمدة 1 أو 2 ثانية.
  5. حفظ / تصدير ملف الصوت. (سيكون لها ملحق .4A وحوالي 2 كيلوبايت على الحجم).
  6. أضف الملف إلى مشروعك ولعبه.

إذا كنت لا ترغب في إنشاء ملف صوت جديد بنفسك، يمكنك تنزيل ملف صوت قصير و Silent هنا: https://www.dropbox.com/s/3u45x9v72ic70tk/silent.m4a؟dl=0.

إليك ملحق سريعا سريعا إلى Avaudioplayer يستخدم المسرحية والإيقاف عند 0 فكرة الحجم المقدمة في الإجابات السابقة. تحضيرتوبلاي () لسوء الحظ على الأقل بالنسبة لي لم تفعل الخدعة.

extension AVAudioPlayer {
    private func initDelaylessPlayback() {
        volume = 0
        play()
        stop()
        volume = 1
    }

    convenience init(contentsOfWithoutDelay : URL) throws {
        try self.init(contentsOf: contentsOfWithoutDelay, fileTypeHint: nil)
        initDelaylessPlayback()
    }
}

لا أعرف بالتأكيد، لكنني أظن أن كائن NSDATA هو كسول وتحميل محتويات الملف عند الطلب. يمكنك تجربة "الغش" عن طريق الاتصال [audioData getBytes:someBuffer length:1]; في وقت مبكر، للحصول عليه لتحميل هذا الملف قبل أن تكون هناك حاجة إليها.

الجواب هو

AVAudioPlayer *audioplayer;
[audioplayer prepareToPlay];
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top