Пример #1
0
static ALLEGRO_SAMPLE *create_sample_s16(int freq, int len)
{
   char *buf = al_malloc(freq * len * sizeof(int16_t));

   return al_create_sample(buf, len, freq, ALLEGRO_AUDIO_DEPTH_INT16,
			   ALLEGRO_CHANNEL_CONF_1, true);
}
Пример #2
0
/* emulate create_sample(), for unsigned 8-bit mono samples */
ALLEGRO_SAMPLE *create_sample_u8(int freq, int len)
{
   char *buf = malloc(freq * len);

   return al_create_sample(buf, len, freq, ALLEGRO_AUDIO_DEPTH_UINT8,
			   ALLEGRO_CHANNEL_CONF_1, true);
}
Пример #3
0
ALLEGRO_SAMPLE* finish_sample(float* buffer, int buffer_length)
{


 ALLEGRO_SAMPLE* new_sample = al_create_sample(buffer, buffer_length, SAMPLE_FREQUENCY, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_1, 0);

 if (new_sample == NULL)
	{
		  fprintf(stdout, "\nError: x_synth.c: finish_sample(): failed to create sample.");
    error_call();
	}

 return new_sample;

}
Пример #4
0
/* Function: al_load_ogg_vorbis_f
 */
ALLEGRO_SAMPLE *al_load_ogg_vorbis_f(ALLEGRO_FILE* file)
{
   /* Note: decoding library returns floats.  I always return 16-bit (most
    * commonly supported).
    */
#ifdef ALLEGRO_LITTLE_ENDIAN
   const int endian = 0; /* 0 for Little-Endian, 1 for Big-Endian */
#else
   const int endian = 1; /* 0 for Little-Endian, 1 for Big-Endian */
#endif
   int word_size = 2; /* 1 = 8bit, 2 = 16-bit. nothing else */
   int signedness = 1; /* 0  for unsigned, 1 for signed */
   const int packet_size = 4096; /* suggestion for size to read at a time */
   OggVorbis_File vf;
   vorbis_info* vi;
   char *buffer;
   long pos;
   ALLEGRO_SAMPLE *sample;
   int channels;
   long rate;
   long total_samples;
   int bitstream;
   long total_size;
   AL_OV_DATA ov;

   if (file == NULL) {
      ALLEGRO_WARN("Audio file failed to open.\n");
      return NULL;
   }
   ov.file = file;
   if (ov_open_callbacks(&ov, &vf, NULL, 0, callbacks) < 0) {
      ALLEGRO_WARN("Audio file does not appear to be an Ogg bitstream.\n");
      al_fclose(file);
      return NULL;
   }

   vi = ov_info(&vf, -1);

   channels = vi->channels;
   rate = vi->rate;
   total_samples = ov_pcm_total(&vf, -1);
   bitstream = -1;
   total_size = total_samples * channels * word_size;

   ALLEGRO_DEBUG("channels %d\n", channels);
   ALLEGRO_DEBUG("word_size %d\n", word_size);
   ALLEGRO_DEBUG("rate %ld\n", rate);
   ALLEGRO_DEBUG("total_samples %ld\n", total_samples);
   ALLEGRO_DEBUG("total_size %ld\n", total_size);

   buffer = _AL_MALLOC_ATOMIC(total_size);
   if (!buffer) {
      al_fclose(file);
      return NULL;
   }

   pos = 0;
   while (pos < total_size) {
      /* XXX error handling */
#if !defined(ALLEGRO_GP2XWIZ) && !defined(ALLEGRO_IPHONE)
      long read = ov_read(&vf, buffer + pos, packet_size, endian, word_size,
         signedness, &bitstream);
#else
      (void)endian;
      (void)signedness;
      long read = ov_read(&vf, buffer + pos, packet_size, &bitstream);
#endif
      pos += read;
      if (read == 0)
         break;
   }

   ov_clear(&vf);

   sample = al_create_sample(buffer, total_samples, rate,
      _al_word_size_to_depth_conf(word_size),
      _al_count_to_channel_conf(channels), true);

   if (!sample) {
      _AL_FREE(buffer);
   }

   return sample;
}
Пример #5
0
ALLEGRO_SAMPLE *_al_load_ogg_opus_f(ALLEGRO_FILE *file)
{
   /* Note: decoding library can return 16-bit or floating-point output,
    * both using native endian ordering. (TODO: Implement float output,
    * individual links in the stream...)
    */
   int word_size = 2; /* 2 = 16-bit. */
   const int packet_size = 5760; /* suggestion for size to read at a time */
   OggOpusFile *of;
   opus_int16 *buffer;
   ALLEGRO_SAMPLE *sample;
   int channels;
   long rate;
   ogg_int64_t total_samples;
   int bitstream;
   ogg_int64_t total_size;
   AL_OP_DATA op;
   ogg_int64_t pos;
   long read;

   if (!init_dynlib()) {
      return NULL;
   }

   op.file = file;
   of = lib.op_open_callbacks(&op, &callbacks, NULL, 0, NULL);
   if (!of) {
      ALLEGRO_WARN("Audio file does not appear to be an Ogg bitstream.\n");
      return NULL;
   }

   bitstream = -1;
   channels = lib.op_channel_count(of, bitstream);
   rate = 48000;
   total_samples = lib.op_pcm_total(of, bitstream);
   total_size = total_samples * channels * word_size;

   ALLEGRO_DEBUG("channels %d\n", channels);
   ALLEGRO_DEBUG("word_size %d\n", word_size);
   ALLEGRO_DEBUG("rate %ld\n", rate);
   ALLEGRO_DEBUG("total_samples %ld\n", (long)total_samples);
   ALLEGRO_DEBUG("total_size %ld\n", (long)total_size);

   buffer = al_malloc(total_size);
   if (!buffer) {
      return NULL;
   }

   pos = 0;
   while (pos < total_samples) {
      const int read_size = _ALLEGRO_MIN(packet_size, total_samples - pos);
      ASSERT(pos + read_size <= total_samples);

      /* XXX error handling */
      read = lib.op_read(of, buffer + pos * channels, read_size, NULL);

      pos += read;
      if (read == 0)
         break;
   }

   lib.op_free(of);

   sample = al_create_sample(buffer, total_samples, rate,
      _al_word_size_to_depth_conf(word_size),
      _al_count_to_channel_conf(channels), true);

   if (!sample) {
      al_free(buffer);
   }

   return sample;
}
Пример #6
0
ALLEGRO_SAMPLE *_al_load_voc_f(ALLEGRO_FILE *file)
{
   AL_VOC_DATA *vocdata;
   ALLEGRO_SAMPLE *sample = NULL;
   size_t pos = 0; /* where to write in the buffer */
   size_t read = 0; /*bytes read during last operation */
   char* buffer;

   size_t bytestoread = 0;
   bool endofvoc = false;

   vocdata = al_malloc(sizeof(AL_VOC_DATA));
   memset(vocdata, 0, sizeof(*vocdata));
   /*
    * Open file and populate VOC DATA, then create a buffer for the number of
    * samples of the frst block.
    * Iterate on the following blocks till EOF or terminator block
    */
   vocdata = voc_open(file);
   if (!vocdata) return NULL;

   ALLEGRO_DEBUG("channels %d\n", vocdata->channels);
   ALLEGRO_DEBUG("word_size %d\n", vocdata->sample_size);
   ALLEGRO_DEBUG("rate %d\n", vocdata->samplerate);
   ALLEGRO_DEBUG("first_block_samples %d\n", vocdata->samples);
   ALLEGRO_DEBUG("first_block_size %d\n", vocdata->samples * vocdata->sample_size);

   /*
    * Let's allocate at least the first block's bytes;
    */
   buffer = al_malloc(vocdata->samples * vocdata->sample_size);
   if (!buffer) {
      return NULL;
   }
   /*
    * We now need to iterate over data blocks till either we hit end of file
    * or we find a terminator block.
    */
   bytestoread = vocdata->samples * vocdata->sample_size;
   while(!endofvoc && !al_feof(vocdata->file)) {
      uint32_t blocktype = 0;
      uint32_t x = 0, len = 0;
      read = al_fread(vocdata->file, buffer, bytestoread);
      pos += read;
      READNBYTES(vocdata->file, blocktype, 1, NULL);   // read next block type
      if (al_feof(vocdata->file)) break;
      switch (blocktype) {
         case 0:{  /* we found a terminator block */
            endofvoc = true;
            break;
            }
         case 2:{  /*we found a continuation block: unlikely but handled */
            x = 0;
            bytestoread = 0;
            READNBYTES(vocdata->file, bytestoread, 2, NULL);
            READNBYTES(vocdata->file, x, 1, NULL);
            bytestoread += x<<16;
            /* increase subsequently storage */
            buffer = al_realloc(buffer, sizeof(buffer) + bytestoread);
            break;
            }
         case 1:   // we found a NEW data block starter, I assume this is wrong
         case 8:   // and let the so far read sample data correctly in the
         case 9:{   // already allocated buffer.
            endofvoc = true;
            break;
            }
         case 3:     /* we found a pause block */
         case 4:     /* we found a marker block */
         case 5:     /* we found an ASCII c-string block */
         case 6:     /* we found a repeat block */
         case 7:{    /* we found an end repeat block */
                     /* all these blocks will be skipped */
            unsigned int ii;
            len = 0;
            x = 0;
            READNBYTES(vocdata->file, len, 2, NULL);
            READNBYTES(vocdata->file, x, 1, NULL);
            len += x<<16;  // this is the length what's left to skip */
            for (ii = 0; ii < len ; ++ii) {
               al_fgetc(vocdata->file);
            }
            bytestoread = 0;  //should let safely check for the next block */
            break;
            }
         default:
            break;
      }
   }

   sample = al_create_sample(buffer, pos, vocdata->samplerate,
                             _al_word_size_to_depth_conf(vocdata->sample_size),
                             _al_count_to_channel_conf(vocdata->channels),
                             true);
   if (!sample)
      al_free(buffer);

   voc_close(vocdata);

   return sample;
}
Пример #7
0
int main(int argc, char *argv[])
{
   ALLEGRO_DISPLAY *display;
   ALLEGRO_FONT *font;
   ALLEGRO_AUDIO_RECORDER *recorder;
   ALLEGRO_EVENT_QUEUE *queue;
   ALLEGRO_TIMER *timer;
   int font_height;
   
   /* Frequency is the number of samples per second. */
   const int frequency = 44100;
   
   const int channels = 2;

   /* The latency is used to determine the size of the fragment buffer.
      More accurately, it represents approximately how many seconds will
      pass between fragment events. (There may be overhead latency from
      the OS or driver the adds a fixed amount of latency on top of 
      Allegro's.) 
      
      For this example, the latency should be kept relatively low since
      each fragment is processed in its entirety. Increasing the latency
      would increase the size of the fragment, which would decrease the
      accuracy of the code that processes the fragment.
      
      But if it's too low, then it will cut out too quickly. (If the
      example were more thoroughly written, the latency setting wouldn't
      actually change how the voice detection worked.)
    */
   const float latency = 0.10;

   const int max_seconds = 3; /* number of seconds of voice recording */
   
   int16_t *name_buffer;      /* stores up to max_seconds of audio */
   int16_t *name_buffer_pos;  /* points to the current recorded position */
   int16_t *name_buffer_end;  /* points to the end of the buffer */
   
   float gain = 0.0f;         /* 0.0 (quiet) - 1.0 (loud) */
   float begin_gain = 0.3f;   /* when to begin recording */
   
   bool is_recording = false;
   
   ALLEGRO_SAMPLE *spl = NULL;
   
   (void) argc;
   (void) argv;
   
   if (!al_init()) {
      abort_example("Could not init Allegro.\n");
   }
   
   if (!al_install_audio()) {
      abort_example("Unable to initialize audio addon\n");
   }
   
   if (!al_init_acodec_addon()) {
      abort_example("Unable to initialize acoded addon\n");
   }
   
   if (!al_init_image_addon()) {
      abort_example("Unable to initialize image addon\n");
   }
   
   if (!al_init_primitives_addon()) {
      abort_example("Unable to initialize primitives addon\n");
   }
      
   al_init_font_addon();
   al_install_keyboard();
   
   font = al_load_bitmap_font("data/bmpfont.tga");
   if (!font) {
      abort_example("Unable to load data/a4_font.tga\n");
   }
   
   font_height = al_get_font_line_height(font);
   
   /* WARNING: This demo assumes an audio depth of INT16 and two channels.
      Changing those values will break the demo. Nothing here really needs to be
      changed. If you want to fiddle with things, adjust the constants at the
      beginning of the program.
    */
   
   recorder = al_create_audio_recorder(
      5 / latency,                 /* five seconds of buffer space */
      frequency * latency,         /* configure the fragment size to give us the given
                                        latency in seconds */
      frequency,                   /* samples per second (higher => better quality) */
      ALLEGRO_AUDIO_DEPTH_INT16,   /* 2-byte sample size */
      ALLEGRO_CHANNEL_CONF_2       /* stereo */
   );
   
   if (!recorder) {
      abort_example("Unable to create audio recorder\n");
   }
   
   display = al_create_display(640, 480);
   if (!display) {
      abort_example("Unable to create display\n");
   }
   
   /* Used to play back the voice recording. */
   al_reserve_samples(1);
   
   /* store up to three seconds */
   name_buffer = al_calloc(channels * frequency * max_seconds, sizeof(int16_t));
   name_buffer_pos = name_buffer;
   name_buffer_end = name_buffer + channels * frequency * max_seconds;
   
   queue = al_create_event_queue();
   timer = al_create_timer(1 / 60.0);
   
   al_register_event_source(queue, al_get_display_event_source(display));
   al_register_event_source(queue, al_get_audio_recorder_event_source(recorder));
   al_register_event_source(queue, al_get_timer_event_source(timer));
   al_register_event_source(queue, al_get_keyboard_event_source());
   
   al_start_timer(timer);
   al_start_audio_recorder(recorder);
   
   while (true) {
      ALLEGRO_EVENT event;
      bool do_draw = false;
      
      al_wait_for_event(queue, &event);
      
      if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE || 
         (event.type == ALLEGRO_EVENT_KEY_UP && event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)) {
         break;
      }
      else if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
         if (spl && event.keyboard.unichar != 27) {
            al_play_sample(spl, 1.0, 0.0, 1.0, ALLEGRO_PLAYMODE_ONCE, NULL);
         }
      }
      else if (event.type == ALLEGRO_EVENT_TIMER) {
         do_draw = true;
      }
      else if (event.type == ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT && recorder != NULL) {
         /* Because the recording happens in a different thread (and simply because we are
            queuing up events), it's quite possible to receive (process) a fragment event
            after the recorder has been stopped or destroyed. Thus, it is important to
            somehow check that the recorder is still valid, as we are doing above.
          */
         ALLEGRO_AUDIO_RECORDER_EVENT *re = al_get_audio_recorder_event(&event);
         int16_t *buffer = re->buffer;
         int16_t low = 0, high = 0;
         unsigned int i;
         
         /* Calculate the volume by comparing the highest and lowest points. This entire
            section assumes we are using fairly small fragment size (low latency). If a 
            large fragment size were used, then we'd have to inspect smaller portions 
            of it at a time to more accurately deterine when recording started and
            stopped. */
         for (i = 0; i < channels * re->samples; ++i) {
            if (buffer[i] < low)
               low = buffer[i];
            else if (buffer[i] > high)
               high = buffer[i];
         }
         
         gain = gain * 0.25 + ((float) (high - low) / 0xffff) * 0.75;
         
         /* Set arbitrary thresholds for beginning and stopping recording. This probably
            should be calibrated by determining how loud the ambient noise is.
          */
         if (!is_recording && gain >= begin_gain && name_buffer_pos == name_buffer)
            is_recording = true;
         else if (is_recording && gain <= 0.10)
            is_recording = false;
         
         if (is_recording) {
            /* Copy out of the fragment buffer into our own buffer that holds the
               name. */
            int samples_to_copy = channels * re->samples;
            
            /* Don't overfill up our name buffer... */
            if (samples_to_copy > name_buffer_end - name_buffer_pos)
               samples_to_copy = name_buffer_end - name_buffer_pos;
            
            if (samples_to_copy) {
               /* must multiply by two, since we are using 16-bit samples */
               memcpy(name_buffer_pos, re->buffer, samples_to_copy * 2);
            }
            
            name_buffer_pos += samples_to_copy;
            if (name_buffer_pos >= name_buffer_end) {
               is_recording = false;
            }
         }
         
         if (!is_recording && name_buffer_pos != name_buffer && !spl) {
            /* finished recording, but haven't created the sample yet */
            spl = al_create_sample(name_buffer, name_buffer_pos - name_buffer, frequency, 
               ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2, false);
            
            /* We no longer need the recorder. Destroying it is the only way to unlock the device. */
            al_destroy_audio_recorder(recorder);
            recorder = NULL;
         }
      }
      
      if (do_draw) {
         al_clear_to_color(al_map_rgb(0,0,0));
         if (!spl) {
            const char *msg = "Say Your Name";
            int width = al_get_text_width(font, msg);
            
            al_draw_text(font, al_map_rgb(255,255,255),
               320, 240 - font_height / 2, ALLEGRO_ALIGN_CENTRE, msg
            );
            
            /* draw volume meter */
            al_draw_filled_rectangle(320 - width / 2, 242 + font_height / 2,
               (320 - width / 2) + (gain * width), 242 + font_height, 
               al_map_rgb(0,255,0)
            );
            
            /* draw target line that triggers recording */
            al_draw_line((320 - width / 2) + (begin_gain * width), 242 + font_height / 2,
               (320 - width / 2) + (begin_gain * width), 242 + font_height,
               al_map_rgb(255,255,0), 1.0
            );
         }
         else {
            al_draw_text(font, al_map_rgb(255,255,255), 320, 240 - font_height / 2,
               ALLEGRO_ALIGN_CENTRE, "Press Any Key");
         }
         al_flip_display();
      }
   }
   
   if (recorder) {
      al_destroy_audio_recorder(recorder);
   }
   
   al_free(name_buffer);
   
   return 0;
}