2010-11-27 26 views
0

Ma question est un peu compliquée, et je ne suis pas vraiment expérimenté (je pourrais avoir des termes faux), alors voilà. Je déclare une instance d'un objet appelé "Singer". L'instance s'appelle "singer1". "singer1" produit un signal audio. Maintenant, voici le code où les spécificités du signal audio sont déterminés:Aide pour la mise à jour en direct du son sur l'iPhone

OSStatus playbackCallback(void *inRefCon, 
         AudioUnitRenderActionFlags *ioActionFlags, 
         const AudioTimeStamp *inTimeStamp, 
         UInt32 inBusNumber, 
         UInt32 inNumberFrames, 
         AudioBufferList *ioData) {  

//Singer *me = (Singer *)inRefCon; 

static int phase = 0; 

for(UInt32 i = 0; i < ioData->mNumberBuffers; i++) { 

    int samples = ioData->mBuffers[i].mDataByteSize/sizeof(SInt16); 

    SInt16 values[samples]; 

    float waves; 
    float volume=.5; 

    for(int j = 0; j < samples; j++) { 


     waves = 0; 


     waves += sin(kWaveform * 600 * phase)*volume; 
     waves += sin(kWaveform * 400 * phase)*volume; 
     waves += sin(kWaveform * 200 * phase)*volume; 
     waves += sin(kWaveform * 100 * phase)*volume;    

     waves *= 32500/4; // <--------- make sure to divide by how many waves you're stacking 

     values[j] = (SInt16)waves; 
     values[j] += values[j]<<16; 

     phase++; 

    } 

    memcpy(ioData->mBuffers[i].mData, values, samples * sizeof(SInt16)); 

} 

return noErr; 

}

99% de ce code est emprunté, donc je n'ai qu'une connaissance de base de la façon dont cela fonctionne (I Je ne connais pas la classe ou la méthode OSStatus ou quoi que ce soit, mais vous voyez ces 4 lignes avec 600, 400, 200 et 100 qui déterminent la fréquence, maintenant ce que je veux faire est pour le moment. insérer ma propre variable à la place d'une constante, que je peux changer sur un caprice.Cette variable est appelée "fr1". "fr1" est déclaré dans le fichier d'en-tête, mais si j'essaie de compiler, j'obtiens une erreur " En ce moment, ma technique pour résoudre ce problème est la suivante: Neath où je #import des choses, ajouter la ligne

fr1=0.0;//any number will work properly 

Ce genre de travaux, que le code compile et singer1.fr1 changera réellement les valeurs si je dis à. Les problèmes sont maintenant ceci: A) même si cela compile et la tonalité spécifiée jouera (0.0 est pas de ton), j'obtiens les avertissements "La définition de données n'a aucun type ou classe de stockage" et "Type par défaut à 'int' dans la déclaration de 'fr1' ". Je parie que c'est parce que pour une raison quelconque, il ne voit pas ma déclaration précédente dans le fichier d'en-tête (comme un flotteur). Cependant, encore une fois, si je laisse cette ligne, le code ne compilera pas car "fr1 n'est pas déclaré". B) Juste parce que je change la valeur de fr1 ne signifie pas que chanteur1 mettra à jour la valeur stockée dans la variable "playbackcallback" ou tout ce qui est en charge de la mise à jour des tampons de sortie. Peut-être cela peut-il être corrigé en codant différemment? C) même si cela a fonctionné, il y a toujours un "écart" perceptible lors de la pause/lecture de l'audio, que je dois éliminer. Cela pourrait signifier une refonte complète du code afin que je puisse «insérer dynamiquement» de nouvelles valeurs sans perturber quoi que ce soit. Cependant, la raison pour laquelle je fais tout ce travail est que cette méthode fait exactement ce que je veux (je peux calculer une valeur mathématiquement et ça va directement au DAC, ce qui signifie que je peux l'utiliser dans le futur pour faire un triangle , carré, etc vagues facilement). J'ai téléchargé Singer.h et .m à pastebin pour votre plaisir, peut-être qu'ils vont aider. Désolé, je ne peux pas poster 2 balises HTML alors voici les liens complets. (http://pastebin.com/ewhKW2Tk) (http://pastebin.com/CNAT4gFv)

Ainsi, TL; DR, tout ce que je veux vraiment faire est d'être en mesure de définir l'équation/valeur actuelle des 4 vagues et les redéfinir très souvent sans un écart dans le son. Merci. (Et désolé si le post était déroutant ou hors de la piste, ce que je suis sûr qu'il l'a fait.)

Répondre

1

Je comprends que votre fonction de rappel est appelée à chaque fois que le tampon doit être rempli à nouveau. Donc changer fr1..fr4 changera la forme d'onde, mais seulement quand le tampon sera mis à jour. Vous ne devriez pas avoir besoin d'arrêter et de redémarrer le son pour obtenir un changement, mais vous remarquerez un changement brusque du timbre si vous changez vos valeurs fr. Afin d'obtenir une transition en douceur dans le timbre, vous devez implémenter quelque chose qui modifie doucement les valeurs fr au fil du temps. Le réglage de la taille de la mémoire tampon vous donne un certain contrôle sur la réactivité du son à vos valeurs fr en cours de modification.

Votre problème avec fr étant indéfini est dû au fait que votre callback est une fonction rectiligne. Vos variables fr sont déclarées en tant que variables d'instance objectives-c dans le cadre de votre objet Singer. Ils ne sont pas accessibles par défaut.

jetez un oeil à ce projet, et voyez comment il implémente l'accès à ses variables d'instance depuis son rappel.Fondamentalement, il passe une référence à son instance à la fonction de rappel, puis accède à des variables d'instance à travers cela.

https://github.com/youpy/dowoscillator

avis:

Sinewave *sineObject = inRefCon; 
float freq = sineObject.frequency * 2 * M_PI/samplingRate; 

et:

AURenderCallbackStruct input; 
input.inputProc = RenderCallback; 
input.inputProcRefCon = self; 

, vous aurez également déplacer votre fonction de rappel en dehors de votre bloc @implementation, car il est ne fait pas partie de votre objet Singer.

Vous pouvez voir tout cela en action ici: https://github.com/coryalder/SineWaver

+0

Hey Kenny, Merci pour votre réponse. Je pense que je comprends ce qu'il fait, est-ce qu'il transforme les variables objectives c en un pointeur auquel le code C peut accéder? L'opérateur -> est comme "." mais pour un pointeur, non? Quoi qu'il en soit, @defs() ne fonctionne plus ... Xcode dit que "@defs n'est pas supporté par new abi". Que puis-je faire à la place? Aussi, à quelle fréquence le tampon est-il mis à jour? Parce que je n'ai pas entendu le son changer même si j'ai confirmé que la valeur de singer1.fr1 a changé (en le transformant en une chaîne et en la passant à UILabel). Aussi, où dois-je déplacer la fonction de rappel à? Merci beaucoup! – wyager

+0

Je l'ai édité pour être plus précis ... la chose entière @defs fait une c-struct d'un objet c objectif ... pas la meilleure façon de le faire. Si vous avez des propriétés configurées, vous pouvez simplement utiliser la notation point c objective pour accéder aux valeurs. Quoi qu'il en soit, pour m'assurer que je ne fumais pas seulement de la fumée, j'ai mis en place un nouveau projet pour que tout fonctionne. Check it out https://github.com/coryalder/SineWaver –

+0

Je pense que le tampon par défaut est 1024 octets .. vous pouvez entendre si vous bougez les curseurs rapidement dans mon projet SineWaver les pops que la forme d'onde change brusquement chaque fois que le tampon re -fills. –