Question

Je suis en train d'éliminer le décalage de démarrage lors de la lecture d'un (très court - moins de 2 secondes). Fichier audio via AVAudioPlayer sur l'iPhone

Tout d'abord, le 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];

Je installe également la méthode audioPlayerDidFinishPlaying pour libérer le AVAudioPlayer une fois que je suis fait.

La première fois que je joue le son du retard est palpable - au moins 2 secondes. Cependant, après que le son joue immédiatement. Je soupçonne que le coupable, alors, est le [NSData dataWithContentsOfMappedFile] prendre beaucoup de temps la lecture du flash au départ, mais étant alors rapidement sur lit plus tard. Je ne sais pas comment tester, cependant.

Est-ce le cas? Si oui, dois-je juste avant cache les objets NSData et être agressifs à leur sujet dans la compensation des conditions de mémoire?

Était-ce utile?

La solution

Le retard semble être lié à l'instanciation AVAudioPlayer pour la première fois. Si je charge de l'audio, exécutez [Audioplayer prepareToPlay] puis relâchez immédiatement, le temps de chargement pour tous mes autres audio est très proche imperceptible. Alors maintenant, je fais que applicationDidFinishLaunching et tout le reste fonctionne bien.

Je ne trouve rien à ce sujet dans la documentation, mais il semble certainement être le cas.

Autres conseils

Voici ce que je l'ai fait (dans un thread séparé):

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

[audioplayer prepareToPlay] semble être une méthode asynchrone, de sorte que vous ne pouvez pas être sûr quand il retourne si le son est en fait prêt à jouer.

Dans mon cas, j'appelle début de réellement commencer à jouer - cela semble être synchrone. Puis-je arrêter immédiatement. Dans le simulateur de toute façon je n'entends aucun son qui sort de cette activité. Maintenant que le son est « vraiment » prêt à jouer, j'attribue la variable locale à une variable membre si le code en dehors du fil a accès.

Je dois dire que je trouve cela un peu surprenant de constater que, même sur iOS 4, il prend quelques 2 secondes juste pour charger un fichier audio qui est seulement 4 secondes de longueur ....

Si votre audio est inférieure à 30 secondes de long en longueur et est au format PCM ou IMA4 linéaire, et est emballé comme un .caf, .wav ou .aiff vous pouvez utiliser les sons du système:

Importer le cadre AudioToolbox

Dans votre fichier .h créer cette variable:

SystemSoundID mySound;

Dans votre fichier .m mettre en œuvre dans votre méthode init:

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

Dans la méthode IBAction vous appelez le son avec ceci:

AudioServicesPlaySystemSound(mySound);

Cela fonctionne pour moi, joue le son sacrément proche lorsque le bouton est pressé. Espérons que cela vous aide.

J'ai pris une autre approche qui fonctionne pour moi. Je l'ai vu cette technique mentionnée ailleurs (quoique je ne me souviens pas au moment où cela a été).

En bref, le système de contrôle en amont par son chargement et la lecture d'un court, son « blanc » avant de faire quoi que ce soit d'autre. Le code ressemble à ceci pour un petit fichier mp3 je précharger selon moi méthode controller'sviewDidLoad qui est de 0,1 secondes la durée:

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

Vous pouvez créer votre propre mp3 vide si vous voulez, ou faire une recherche google sur « mp3s blanc » pour trouver et télécharger un déjà construit par quelqu'un d'autre.

J'ai écrit un emballage simple pour AVAudioPlayer qui fournit une méthode de prepareToPlay qui fonctionne réellement:

https://github.com/nicklockwood/SoundManager

Il fondamentalement juste analyse votre application pour les fichiers sonores, prend un et il joue à zéro volume. Ce initialise le matériel audio et permet le son à côté de jouer instantanément.

Autre solution consiste à créer un court audio et silencieux et jouer sur le premier joueur du temps est lancé.

  1. Régler le niveau du microphone à 0 sur Préférences Système.
  2. Ouvrez QuickTime.
  3. Créer un nouvel enregistrement audio (Fichier> Nouvel enregistrement audio).
  4. Enregistrer 1 ou 2 secondes.
  5. Enregistrer / Exporter le fichier audio. (Il aura .m4a l'extension et à environ 2 kb sur la taille).
  6. Ajoutez le fichier à votre projet et jouer.

Si vous ne voulez créer un nouveau fichier vous-même son, vous pouvez télécharger un fichier audio court et silencieux ici: https://www.dropbox.com/s/3u45x9v72ic70tk/silent.m4a?dl=0

Voici une simple extension Swift à AVAudioPlayer qui utilise le jeu et arrêt à 0 idée du volume présenté dans les réponses précédentes. PrepareToPlay () malheureusement au moins pour moi ne pas faire l'affaire.

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

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

Je ne suis pas sûr, mais je soupçonne que l'objet NSData est d'être paresseux et charger le contenu du fichier sur la demande. Vous pouvez essayer « tricher » en appelant [audioData getBytes:someBuffer length:1]; à un moment donné tôt pour obtenir pour charger ce fichier avant qu'il ne soit nécessaire.

La réponse est

AVAudioPlayer *audioplayer;
[audioplayer prepareToPlay];
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top