Frage

Ich versuche Startverzögerung zu beseitigen, wenn ein (sehr kurz - weniger als 2 Sekunden) zu spielen. Audiodatei über AVAudioPlayer auf dem iPhone

Zuerst wird der Code:

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];

ich implementieren auch die audioPlayerDidFinishPlaying Methode, um die AVAudioPlayer freizugeben, sobald ich fertig bin.

Das erste Mal, dass ich das Audio spielt die Verzögerung ist spürbar - mindestens 2 Sekunden. unmittelbar danach jedoch spielt der Klang. Ich vermute, dass der Täter, dann ist das [NSData dataWithContentsOfMappedFile] eine lange Zeit aus der Flash-Lesen nimmt zunächst, aber dann schnell zu sein später liest. Ich bin mir nicht sicher, wie das zu testen, though.

Ist das der Fall? Wenn ja, soll ich nur Pre-Cache der NSData Objekte und aggressiv über sie in niedrigeren Speicherbedingungen Clearing?

War es hilfreich?

Lösung

Die Verzögerung scheint Instanziieren AVAudioPlayer zum ersten Mal zusammenhängen. Wenn ich alle Audio laden, führen Sie [Audioplayer prepareToPlay] und dann sofort loslassen, die Ladezeiten für alle meine anderen Audio sehr nahe zu nicht wahrnehmbar. So, jetzt ich, dass in applicationDidFinishLaunching mache und alles andere läuft gut.

Ich kann nichts darüber in der Dokumentation finden, aber es scheint sicher der Fall zu sein.

Andere Tipps

Hier ist, was ich (in einem separaten Thread) getan haben:

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

[Audioplayer prepareToPlay] scheint eine asynchrone Methode zu sein, so dass man nicht sicher sein kann, wenn er zurückkehrt, wenn der Ton in der Tat bereit ist zu spielen.

In meinem Fall habe ich Anfang rufen, um tatsächlich anfangen zu spielen - dies scheint synchron zu sein. Ich kann es dann sofort stoppen. Im Simulator trotzdem höre ich nicht jeder Ton kommt aus dieser Tätigkeit heraus. Nun, da der Klang „wirklich“ bereit zu spielen, ich die lokale Variable auf ein Member-Variable zuweisen, so Code außerhalb des Threads hat Zugriff darauf.

Ich muß sagen, dass ich es etwas überraschend, dass auch auf iOS 4 es etwa 2 Sekunden dauert nur eine Audiodatei zu laden, die nur 4 Sekunden lang ist ....

Wenn Ihr Audio weniger als 30 Sekunden lang in der Länge und ist in linearer PCM oder IMA4-Format und wird als .caf, .wav verpackt oder .aiff Sie System verwenden können, klingt:

das AudioToolbox Rahmen Importieren

In Ihrer .h-Datei diese Variable erstellen:

SystemSoundID mySound;

In .m Datei, um sie in Ihrer init-Methode implementieren:

-(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;
}

In Ihrer IBAction Methode rufen Sie den Ton mit diesem:

AudioServicesPlaySystemSound(mySound);

Das funktioniert für mich, gibt den Ton verdammt nah an, wenn die Taste gedrückt wird. Hoffe, das hilft dir.

Ich habe einen alternativen Ansatz, der für mich arbeitet. Ich habe diese Technik an anderer Stelle erwähnt gesehen (tho mich im Moment nicht daran erinnern, wo das war).

Kurz gesagt, Preflight das Soundsystem durch das Laden und Abspielen eines kurzen, „blank“ Sound, bevor Sie etwas anderes tun. Der Code sieht wie folgt für eine kurze MP3-Datei ich in meiner Ansicht controller'sviewDidLoad Verfahren Vorspannung, die von 0,1 Sekunden Dauer ist:

   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];  

Sie können Ihre eigene leere mp3 erstellen, wenn Sie möchten, oder eine Google-Suche auf „blank mp3s“ zu finden und man schon von jemandem anderen gebaut herunterladen.

Ich schrieb einen einfachen Wrapper für AVAudioPlayer, die eine prepareToPlay Methode bietet, die tatsächlich funktioniert:

https://github.com/nicklockwood/SoundManager

Es im Grunde nur durchsucht Ihre App für Sound-Dateien, nimmt ein und spielt sie auf Null Volumen. Das Initialisieren der Audio-Hardware und ermöglicht es der nächste Ton sofort zu spielen.

Andere Abhilfe ist, ein kurzes & silent-Audio zu erstellen und es auf das erste Mal spielen Spieler eingeleitet werden.

  1. Stellen Sie die Mikrofonpegel auf 0 auf Systemeinstellungen.
  2. Öffnen Sie Quicktime.
  3. Neue Audio-Aufnahme (File> New Audio Recording).
  4. Nehmen Sie für 1 oder 2 Sekunden.
  5. Speichern / Export der Audiodatei. (Es wird .m4a Erweiterung und etwa 2 kb auf Größe haben).
  6. Fügen Sie die Datei auf Ihrem Projekt und spielen es.

Wenn Sie nicht wollen, einen neuen Sound erstellen Datei selbst, können Sie eine kurze & silent Audiodatei hier herunterladen: https://www.dropbox.com/s/3u45x9v72ic70tk/silent.m4a?dl=0

Hier ist eine einfache Swift Erweiterung AVAudioPlayer, die den Spiel-und-Stop bei 0 Volumen Idee in früheren Antworten präsentiert verwendet. PrepareToPlay () leider zumindest für mich hat es nicht getan.

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

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

Ich weiß nicht sicher, aber ich vermute, dass das NSData Objekt faul wird, und den Inhalt der Datei auf Anfrage zu laden. Sie können versuchen, „Betrug“ von [audioData getBytes:someBuffer length:1]; irgend früh ruft es diese Datei zu laden zu bekommen, bevor es benötigt wird.

Die Antwort ist

AVAudioPlayer *audioplayer;
[audioplayer prepareToPlay];
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top