Advertisement
Kaelygon

ukaelToneC.h

Jul 7th, 2023 (edited)
698
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.20 KB | None | 0 0
  1. #pragma once
  2.  
  3. //audio generating and playback functions
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stdint.h>
  7. #include <string.h>
  8. #include <portaudio.h>
  9.  
  10. #include "ukaelTypedefC.h"
  11. #include "ukaelWaveC.h"
  12.  
  13. // Callback function that is called by PortAudio to fill the output buffer
  14. static int audioCallback(
  15.     const void* inputBuffer,
  16.     void* outputBuffer,
  17.     unsigned long framesPerBuffer,
  18.     const PaStreamCallbackTimeInfo* timeInfo,
  19.     PaStreamCallbackFlags statusFlags,
  20.     void* userData
  21. ){
  22.     AudioData* audioData = (AudioData*)userData;
  23.     uint8_t* out = (uint8_t*)outputBuffer;
  24.     size_t remainingData = audioData->size - audioData->position;
  25.     size_t numFrames = framesPerBuffer;
  26.    
  27.     // If there is not enough audio data remaining, fill the buffer with silence
  28.     if (remainingData < framesPerBuffer) {
  29.         numFrames = remainingData;
  30.         for (size_t i = 0; i < numFrames; i++) {
  31.             out[i] = DEFAULT_AMPLITUDE;  // DEFAULT_AMPLITUDE represents silence for unsigned 8-bit audio
  32.         }
  33.     }
  34.    
  35.     // Copy the audio data to the output buffer
  36.     for (size_t i = 0; i < numFrames; i++) {
  37.         out[i] = audioData->data[audioData->position++];
  38.     }
  39.    
  40.     return paContinue;
  41. }
  42.  
  43. //file IO
  44. void audioDataToBin(const char* filename, const AudioData* samples) {
  45.     if(!(samples->size)){
  46.         printf("Nothing to write to file.\n");
  47.     }
  48.  
  49.     // Open the file in binary mode for writing
  50.     FILE* file = fopen(filename, "wb");
  51.     if (file == NULL) {
  52.         printf("Failed to open the file for writing.\n");
  53.         return;
  54.     }
  55.  
  56.     // Write the samples data to the file
  57.     size_t bytesWritten = fwrite(samples->data, sizeof(uint8_t), samples->size, file);
  58.     if (bytesWritten != samples->size) {
  59.         printf("Failed to write the samples data to the file.\n");
  60.     }
  61.  
  62.     // Close the file
  63.     uint8_t closeResult = fclose(file);
  64.     if (closeResult != 0) {
  65.         printf("Failed to close the file.\n");
  66.     }
  67. }
  68.  
  69.  
  70. //Memory functions
  71.  
  72. //Allocate and set to DEFAULT_AMPLITUDE
  73. void sampleAlloc(AudioData* sampleData) {
  74.  
  75.     // Allocate memory for channel->data
  76.     sampleData->data = (uint8_t*)malloc((sampleData->size)*sizeof(uint8_t));
  77.     if (sampleData->data == NULL) {
  78.         // Failed to allocate memory
  79.         printf("Failed to allocate memory for sampleData->data\n");
  80.         return;
  81.     }
  82.  
  83.     // memset to DEFAULT_AMPLITUDE
  84.     memset((void*)sampleData->data, DEFAULT_AMPLITUDE, sampleData->size);
  85.     if (sampleData->data == NULL) {
  86.         printf("Failed set sampleData to silent.\n");
  87.         return;
  88.     }
  89. }
  90.  
  91. //Free AudioData .data
  92. void sampleFree(AudioData* sampleData) {
  93.     free((void*)sampleData->data);
  94. }
  95.  
  96. // Copy and allocate AudioData to destin from source
  97. void sampleCopy(AudioData* destin, const AudioData* source) {
  98.     if((destin->size)!=(source->size)){
  99.         printf("Failed to copy samples, different size.\n");
  100.         destin->size=0;
  101.         return;
  102.     }
  103.     memcpy((void*)destin->data, (void*)source->data, source->size);
  104.     if (destin->data == NULL) {
  105.         printf("Failed to copy samples.\n");
  106.         return;
  107.     }
  108. }
  109.  
  110. //Tone generation
  111.  
  112. //List of waveform functions
  113. const WaveMap waveList[] = {
  114.     //(uint8)
  115.     {"lsine",       ukaeLSine       },
  116.     {"testing",     testing         },
  117.     {"sine",        ukaelSine       },
  118.     {"csine",       ukaelCSine      },
  119.     {"triangle",    ukaelTriangle   },
  120.     {"saw",         ukaelSaw        },
  121.     {"square",      ukaelSquare     },
  122.     {"noise",       ukaelNoise      },
  123.     {"wnoise",      ukaelWNoise     },
  124.     {"pulse",       ukaelPulse      },
  125.     {"sinef",       ukaelSinef      },
  126.     {"rwalk",       ukaelRWalk      }
  127. };
  128.  
  129.  
  130. //Number of elements in the mapping table
  131. const size_t waveCount = sizeof(waveList) / sizeof(waveList[0]);
  132.  
  133. // generate and store waveform to buffer
  134. const void generateTone(
  135.     AudioData* samples,
  136.     uint8_t amplitude,
  137.     const char* waveKey,
  138.     WaveArg* wargs
  139. ) {
  140.  
  141.     // Find the waveform function pointers based on the string identifier
  142.     ukaelWave waveFunc = NULL;
  143.     for (size_t i = 0; i < waveCount; ++i) {
  144.         if (strcmp(waveKey, waveList[i].id) == 0) {
  145.             waveFunc = waveList[i].waveFunc;
  146.             break;
  147.         }
  148.     }
  149.     if(waveFunc==NULL){
  150.         printf("Invalid key!\n");
  151.         return;
  152.     }
  153.  
  154.     // Generate
  155.     uint16_t value;
  156.     for (uint32_t i = 0; i < (samples->size); ++i) {
  157.         wargs->time = i;
  158.        
  159.         //Generate and pass arguments
  160.         value = waveFunc(wargs);
  161.  
  162.         value = ((value * amplitude)>>8) + ((UINT8_MAX - amplitude)>>1); // Amplitude
  163.         *&samples->data[i] = value;
  164.     }
  165.  
  166.     return;
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement