10
votes

iOS: Comment lire un fichier audio dans un tampon de flotteur

J'ai un fichier audio vraiment court, dites un 10ème de seconde dans (disons) format .PCM

Je veux utiliser Remoteio pour boucler dans le fichier à plusieurs reprises pour produire une tonalité musicale continue. Alors, comment puis-je lire ceci dans un tableau de flotteurs?

Edit: pendant que je pouvais probablement creuser le format de fichier, extraire le fichier en nsdata et le traiter manuellement, je suppose qu'il existe une approche générique plus sensée ... (que par exemple, des copies avec des formats différents)


2 commentaires

Pourquoi une nsdata du fichier ne suffira-t-elle pas?


Je suppose que chaque format de fichier audio aura des informations d'en-tête. Sinon, comment savoir la fréquence d'échantillonnage / le format de données, etc.?


4 Réponses :


5
votes

Je ne connais pas la Remoteio, mais je connais avec WAV et pensé que je posterais des informations de format sur eux. Si vous en avez besoin, vous devriez être capable d'analyser facilement des informations telles que la durée, le débit binaire, etc.

Premièrement, voici un excellent site Web détaillant le Format SoundFile SoundFile d'onde . Ce site fait également un excellent travail illustrant ce que les différentes adresses d'octets à l'intérieur du sous-morceau "FMT" se rapportent à. P>

Format de fichier d'onde h2>
  • Une vague est composée d'un morceau de "riff" et de sous-morceaux ultérieurs li>
  • Chaque morceau est au moins 8 octets li>
  • Les 4 premiers octets sont l'identifiant de morceau li>
  • Suivant 4 octets est la taille du morceau (la taille du morceau donne la taille du reste du morceau, à l'exclusion des 8 octets utilisés pour l'identifiant de morceau et la taille du morceau) li>
  • Chaque vague a les morceaux / sous-morceaux suivants
    • "riff" (premier et unique morceau. Tous les autres sont techniquement sous-morceaux.) li>
    • "FMT" (généralement le premier sous-morceau après "Riff", mais peut être n'importe où entre "Riff" et "Données". Ce morceau contient des informations sur la WAV, telles que le nombre de canaux, de la fréquence d'échantillonnage et du taux d'octet) li>
    • "Data" (doit être le dernier sous-morceau et contient toutes les données sonores) li> ul> li> ul>

      Formats audio courants communs: H2>
      • PCM LI>
      • ieee_float li>
      • pcm_exttensible (avec un sous-format de PCM ou IEEE_FLOAT) LI> ul>

        Durée et taille d'onde h2>

        Une durée d'un fichier d'onde peut être calculée comme suit: p> xxx pré>

        où p>

        DataChunkSize = seconds * ByteRate
        


0 commentaires

18
votes

Vous pouvez utiliser ExtaudiOfile pour lire des données à partir de tout format de données pris en charge dans de nombreux formats de clients. Voici un exemple de lecture d'un fichier sous forme d'entiers 16 bits: xxx

Si vous vouliez des données float32, vous seriez configuré format comme ceci: xxx


2 commentaires

On dirait que vous avez trouvé une API supérieure pour la lecture de fichiers audio, mais une partie du code me confond. Spécifiquement, pouvez-vous définir le format à l'aide de extordiofileSetProperty (...) , et si vous le faites, cela fait-il une sorte de conversion de données pour vous puisque la WAV peut avoir un format différent de celui spécifié? Honnêtement, je suis curieux de savoir. Je n'étais pas au courant du Services de fichiers audio étendus jusqu'à ce que vous ayez posté, donc je n'ai aucune expérience avec elle.


ExtendediOfile est un wrapper autour d'une combinaison d'un Audiofile et un Audioconverter . Quel que soit le format client défini pour être utilisé dans les appels vers EverAtudioOfilerADAD ET ETADONOFILEWRITWRITE ET L'AUDIOOconverter Convertissez du format client aux données du fichier. format.



6
votes

Ceci est le code que j'ai utilisé pour convertir mes données audio (fichier audio) en représentation de point flottant et enregistré dans une matrice.

-(void) PrintFloatDataFromAudioFile {

NSString *  name = @"Filename";  //YOUR FILE NAME
NSString * source = [[NSBundle mainBundle] pathForResource:name ofType:@"m4a"]; // SPECIFY YOUR FILE FORMAT

const char *cString = [source cStringUsingEncoding:NSASCIIStringEncoding];

CFStringRef str = CFStringCreateWithCString(
                                            NULL,
                                            cString,
                                            kCFStringEncodingMacRoman
                                            );
CFURLRef inputFileURL = CFURLCreateWithFileSystemPath(
                                                      kCFAllocatorDefault,
                                                      str,
                                                      kCFURLPOSIXPathStyle,
                                                      false
                                                      );

ExtAudioFileRef fileRef;
ExtAudioFileOpenURL(inputFileURL, &fileRef);


  AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = 44100;   // GIVE YOUR SAMPLING RATE 
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat;
audioFormat.mBitsPerChannel = sizeof(Float32) * 8;
audioFormat.mChannelsPerFrame = 1; // Mono
audioFormat.mBytesPerFrame = audioFormat.mChannelsPerFrame * sizeof(Float32);  // == sizeof(Float32)
audioFormat.mFramesPerPacket = 1;
audioFormat.mBytesPerPacket = audioFormat.mFramesPerPacket * audioFormat.mBytesPerFrame; // = sizeof(Float32)

// 3) Apply audio format to the Extended Audio File
ExtAudioFileSetProperty(
                        fileRef,
                        kExtAudioFileProperty_ClientDataFormat,
                        sizeof (AudioStreamBasicDescription), //= audioFormat
                        &audioFormat);

int numSamples = 1024; //How many samples to read in at a time
UInt32 sizePerPacket = audioFormat.mBytesPerPacket; // = sizeof(Float32) = 32bytes
UInt32 packetsPerBuffer = numSamples;
UInt32 outputBufferSize = packetsPerBuffer * sizePerPacket;

// So the lvalue of outputBuffer is the memory location where we have reserved space
UInt8 *outputBuffer = (UInt8 *)malloc(sizeof(UInt8 *) * outputBufferSize);



AudioBufferList convertedData ;//= malloc(sizeof(convertedData));

convertedData.mNumberBuffers = 1;    // Set this to 1 for mono
convertedData.mBuffers[0].mNumberChannels = audioFormat.mChannelsPerFrame;  //also = 1
convertedData.mBuffers[0].mDataByteSize = outputBufferSize;
convertedData.mBuffers[0].mData = outputBuffer; //

UInt32 frameCount = numSamples;
float *samplesAsCArray;
int j =0;
    double floatDataArray[882000]   ; // SPECIFY YOUR DATA LIMIT MINE WAS 882000 , SHOULD BE EQUAL TO OR MORE THAN DATA LIMIT

while (frameCount > 0) {
    ExtAudioFileRead(
                     fileRef,
                     &frameCount,
                     &convertedData
                     );
    if (frameCount > 0)  {
        AudioBuffer audioBuffer = convertedData.mBuffers[0];
        samplesAsCArray = (float *)audioBuffer.mData; // CAST YOUR mData INTO FLOAT

       for (int i =0; i<1024 /*numSamples */; i++) { //YOU CAN PUT numSamples INTEAD OF 1024

            floatDataArray[j] = (double)samplesAsCArray[i] ; //PUT YOUR DATA INTO FLOAT ARRAY
              printf("\n%f",floatDataArray[j]);  //PRINT YOUR ARRAY'S DATA IN FLOAT FORM RANGING -1 TO +1
            j++;


        }
    }
}}


1 commentaires

Merci pour l'extrait. J'ai dû utiliser Malloc à init Floatdatarray sur iOS. Autre que cela, fonctionne bien.



2
votes

Mise à jour pour SWIFT 5

Ceci est une fonction simple qui aide à obtenir votre fichier audio dans un tableau de flotteurs. Ceci est destiné à la fois audio mono et stéréo, d'obtenir la deuxième chaîne de l'audio stéréo, juste des échantillons non motivés 2 xxx


0 commentaires