Einfachste Möglichkeit Audio auszugeben

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Einfachste Möglichkeit Audio auszugeben

    Hallo zusammen,

    nachdem ich vor kurzem mit eurer Hilfe in diesem Thread erfolgreich es geschafft habe .wav zu öffnen und zu schreiben, bin ich nun an dem Punkt, dass ich gerne auch noch Audio ausgeben könnte.
    Wie im anderen Thema schon erwähnt, mein Ziel war es nie Software für den Mac zu schreiben, sondern nur C++ Audiosignalverarbeitungs-Code für einen Mikroprozessor unterwegs zu generieren.

    Ich suche nach einer Möglichkeit, meinem default System Audio Ausgang Blockweise Audiosamples zum Playback zu übergeben. Im besten Fall passiert das in meiner Vorstellung einfach so, dass ich einen Audioausgang initialisiere, der alle (Blockgröße/Samplerate) Sekunden eine Callbackfunktion aufruft, welche entweder ein Array mit den neuen Samples zurückgibt oder diese an eine im Stelle ablegt, welche mir durch einen Pointer beim Aufruf der Callbackfunktion übergeben wird. Dachte ich würde zu so etwas haufenweise Samplecode finden, viel was ich gefunden habe bezieht sich aber auf Playback von Audiodateien, was ja nicht meine Baustelle ist, oder erscheint mir als nicht ansatzweise in OS X Frameworks bewanderter User viel zu unverständlich.

    Im Grunde suche ich das C++ Pendant zu MATLABs dsp.AudioPlayer was in meiner Idealvorstellung irgendwie so benutzt werden könnte:

    C-Quellcode

    1. #inlcude "myAlgorithm.h" //schon programmiert, enthält void myAlgorithm::computeBlock(float *inputBlock, float *outputBlock, int blockSize);
    2. #inclued "waveFileIO.h" //auch schon programmiert
    3. #define BLOCKSZE 256
    4. void myCallback(float *newBlockToPlay);
    5. waveFileIO inputFile;
    6. void main(){
    7. inputFile.read("Pfad/zu/Eingangsdatei.wav");
    8. AudioPlayer AP;
    9. AP.setSampleRate(48000);
    10. AP.setBlockSize(BLOCKSIZE);
    11. AP.setCallbackFunction(myCallback);
    12. AP.start();
    13. while(1){
    14. //auf Eingaben reagieren
    15. };
    16. return;
    17. }
    18. void myCallback(float *newBlockToPlay){
    19. float *newInputBlock
    20. newInputBlock=inputFile.getNextFloatBlock(BLOCKSIZE);
    21. myAlgorithm.computeBlock(newInputBlock, newBlockToPlay, BLOCKSIZE);
    22. return;
    23. };
    Alles anzeigen
    Welche der unter OS X möglichen Lösung kommt von der Einfachheit dem oben beschrieben am nähsten?
  • Danke schon mal, das sieht von der Grundstruktur recht verständlich aus. Nur die Argumente der Callbackfunktion bzw. die Struktur des Buffers in dem die neuen Samples gespeichert werden erschließen sich mir noch nicht ganz

    C-Quellcode

    1. /** Callback, um einen Audio-Buffer zu füllen */
    2. OSStatus MyRenderCallback(void* inRefCon,
    3. AudioUnitRenderActionFlags* ioActionFlags,
    4. const AudioTimeStamp* inTimeStamp,
    5. UInt32 inBusNumber,
    6. UInt32 inNumberFrames,
    7. AudioBufferList* ioData) {
    8. double freq = ((AppDelegate*)[NSApp delegate]).frequency;
    9. for (int i=0; i<inNumberFrames; i++) {
    10. Float32 sample = getNextSample(freq);
    11. for (int j=0; j<ioData->mNumberBuffers; j++) {
    12. Float32* base = ioData->mBuffers[j].mData;
    13. for (int k=0; k<ioData->mBuffers[j].mNumberChannels; k++) {
    14. base[i * ioData->mBuffers[j].mNumberChannels + k] = sample;
    15. }
    16. }
    17. }
    18. return 0;
    19. }
    Alles anzeigen
    was genau ist mit einem Frame gemeint? Du berechnest ja ein Sample pro Frame und speicherst diesen wert in alle k channels von allen j Buffern auf Frame i. Ich hätte es mir so vorgestellt, dass es EINEN Buffer gibt mit b Samples die sich wiederum in n Kanäle aufteilen, in welchen ich meine Daten schreibe. Das schreiben des selben Samples in mehrere Buffer erschließt sich mir da nicht wirklich
  • Als ich mich mit CoreAudio beschäftigt habe, ist gerade dazu ein Buch rausgekommen. Ned ganz so einfach das zu handeln... Jedenfalls gibt's auf GitHub die Beispiele zu dem Buch. Sieh dir CH07 an.

    github.com/abbood/Learning-Cor…ster/CH07_AUGraphSineWave

    Wenn das Projekt nicht zu kompilieren geht, dann liegt das an der falschen Version des SDKs. Das musst Du von hand auf aktuell ändern. Hab's gerade ausprobiert. Sinusiiert ohne Probleme...
  • uC_J schrieb:


    was genau ist mit einem Frame gemeint? Du berechnest ja ein Sample pro Frame und speicherst diesen wert in alle k channels von allen j Buffern auf Frame i. Ich hätte es mir so vorgestellt, dass es EINEN Buffer gibt mit b Samples die sich wiederum in n Kanäle aufteilen, in welchen ich meine Daten schreibe. Das schreiben des selben Samples in mehrere Buffer erschließt sich mir da nicht wirklich
    Ein Frame ist die kleinste sinnvolle Zeiteinheit des jeweiligen Audioformats. Im Fall von "rohen Samples" (PCM) ist ein Frame = ein Sample (ist nur bei einigen komprimierten Formaten anders).

    Core Audio unterstützt sowohl interleaved (ein einziger Buffer mit reihum Samples für alle Kanäle) als auch non-interleaved (ein Buffer pro Kanal). Ob die konkrete Audiounit alle Formate unterstützt ist eine andere Frage, aber die AudioBufferList-Struktur kann beides abbilden. Der Render-Callback im Beispiel ist so gebaut, dass er sowohl mit interleaved als auch mit non-interleaved klar kommt (und einfach in alle Kanäle das gleiche Sample wirft, also gleicher Ton auf allen Kanälen). Beides zusammen wird in der Praxis nicht auftreten. In diesem Beispiel ist das Format non-interleaved, also jeweils ein Buffer für links und einer für rechts. Das Format wird in der AudioStreamBasicDescription definiert und dann in der Ausgabe-AudioUnit gesetzt. Falls die AudioUnit das Format nicht unterstützt würde sie an der Stelle meckern.
    Multigrad - 360°-Produktfotografie für den Mac