DUMBA5_PLAYER * dumba5_encapsulate_sigrenderer(DUH_SIGRENDERER * sigrenderer, float volume, long bufsize, int freq)
{
	DUMBA5_PLAYER * dp;
	int n_channels;
	ALLEGRO_CHANNEL_CONF c_conf;

	if (!sigrenderer)
		return NULL;

	dp = (DUMBA5_PLAYER *) malloc(sizeof(*dp));
	if (!dp)
		return NULL;

	n_channels = duh_sigrenderer_get_n_channels(sigrenderer);
	if(n_channels == 1)
	{
		c_conf = ALLEGRO_CHANNEL_CONF_1;
	}
	else
	{
		c_conf = ALLEGRO_CHANNEL_CONF_2;
	}

	/* This restriction is imposed by Allegro. */
	ASSERT(n_channels > 0);
	ASSERT(n_channels <= 2);

	dp->flags = ADP_PLAYING;
	dp->bufsize = bufsize;
	dp->freq = freq;

	dp->stream = al_create_audio_stream(4, bufsize, freq, ALLEGRO_AUDIO_DEPTH_UINT16, c_conf);

	if (!dp->stream) {
		free(dp);
		return NULL;
	}

	dp->stream = al_create_audio_stream(4, bufsize, freq, ALLEGRO_AUDIO_DEPTH_UINT16, c_conf);

	if (!dp->stream) {
		free(dp);
		return NULL;
	}

	dp->volume = volume;
	dp->silentcount = 0;

	return dp;
}
Beispiel #2
0
Datei: audio.c Projekt: EQ4/MSF
void init_audio(void)
{
	al_reserve_samples(num_samples); // Sets up the default mixer
	// Set up the audio stream and mixer attachment
	if (stream)
	{
		if (al_get_mixer_attached(al_get_default_mixer()))
		{
			al_detach_mixer(al_get_default_mixer());
		}
		al_destroy_audio_stream(stream);
	}

	stream = al_create_audio_stream(
		num_fragments,
		size_fragment,
		audio_rate,
		AUDIO_DEPTH,
		CHANNEL_CONF);

	al_attach_audio_stream_to_mixer(stream, al_get_default_mixer());

	al_register_event_source(event_queue, 
		al_get_audio_stream_event_source(stream));

}
Beispiel #3
0
static int allua_audio_stream_create(lua_State * L)
{
   int buffer_count = luaL_checkint(L, 1);
   int samples = luaL_checkint(L, 2);
   int freq = luaL_checkint(L, 3);
   int depth = luaL_checkint(L, 4);
   int chan_conf = luaL_checkint(L, 5);

   ALLEGRO_AUDIO_STREAM *stream =
       al_create_audio_stream(buffer_count, samples, freq, depth, chan_conf);
   if (stream)
      allua_pushaudio_stream(L, stream, true);
   else
      lua_pushnil(L);
   return 1;
}
Beispiel #4
0
/* Function: al_load_ogg_vorbis_audio_stream_f
 */
ALLEGRO_AUDIO_STREAM *al_load_ogg_vorbis_audio_stream_f(ALLEGRO_FILE* file,
	size_t buffer_count, unsigned int samples)
{
   const int word_size = 2; /* 1 = 8bit, 2 = 16-bit. nothing else */
   OggVorbis_File* vf;
   vorbis_info* vi;
   int channels;
   long rate;
   long total_samples;
   long total_size;
   AL_OV_DATA* extra;
   ALLEGRO_AUDIO_STREAM* stream;

   extra = _AL_MALLOC(sizeof(AL_OV_DATA));
   if (extra == NULL) {
      ALLEGRO_ERROR("Failed to allocate AL_OV_DATA struct.\n");
      return NULL;
   }
   
   if (file == NULL) {
      ALLEGRO_WARN("File failed to open\n");
      fprintf(stderr, "File failed to open\n");
      return NULL;
   }
   
   extra->file = file;
   
   vf = _AL_MALLOC(sizeof(OggVorbis_File));
   if (ov_open_callbacks(extra, vf, NULL, 0, callbacks) < 0) {
      ALLEGRO_WARN("ogg: Input does not appear to be an Ogg bitstream.\n");
      al_fclose(file);
      return NULL;
   }

   extra->vf = vf;

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

   extra->vi = vi;

   extra->bitstream = -1;

   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);
	
   stream = al_create_audio_stream(buffer_count, samples, rate,
            _al_word_size_to_depth_conf(word_size),
            _al_count_to_channel_conf(channels));
   if (!stream) {
      free(vf);
      return NULL;
   }

   stream->extra = extra;

   extra->loop_start = 0.0;
   extra->loop_end = ogg_stream_get_length(stream);
   stream->feed_thread = al_create_thread(_al_kcm_feed_stream, stream);
   stream->quit_feed_thread = false;
   stream->feeder = ogg_stream_update;
   stream->rewind_feeder = ogg_stream_rewind;
   stream->seek_feeder = ogg_stream_seek;
   stream->get_feeder_position = ogg_stream_get_position;
   stream->get_feeder_length = ogg_stream_get_length;
   stream->set_feeder_loop = ogg_stream_set_loop;
   stream->unload_feeder = ogg_stream_close;
   al_start_thread(stream->feed_thread);
	
   return stream;
}
Beispiel #5
0
static ALLEGRO_AUDIO_STREAM *modaudio_stream_init(ALLEGRO_FILE* f,
   size_t buffer_count, unsigned int samples
#if (DUMB_MAJOR_VERSION) < 2
   /* For DUMB 0.9.3, we must choose a loader function ourselves. */
   , DUH *(loader)(DUMBFILE *)
#endif
)
{
   ALLEGRO_AUDIO_STREAM *stream;
   DUMBFILE *df;
   DUH_SIGRENDERER *sig = NULL;
   DUH *duh = NULL;
   DUMB_IT_SIGRENDERER *it_sig = NULL;
   int64_t start_pos = -1;

   df = lib.dumbfile_open_ex(f, &dfs_f);
   if (!df) {
      ALLEGRO_ERROR("dumbfile_open_ex failed.\n");
      return NULL;
   }

   start_pos = al_ftell(f);

#if (DUMB_MAJOR_VERSION) >= 2
   /*
    * DUMB 2.0 introduces dumb_read_any. It takes two extra int arguments.
    *
    * The first int, restrict_, changes how a MOD module is interpreted.
    * int restrict_ is a two-bit bitfield, and 0 is a good default.
    * For discussion, see: https://github.com/kode54/dumb/issues/53
    *
    * The second int, subsong, matters only for very few formats.
    * A5 doesn't allow to choose a subsong from the 5.2 API anyway, thus 0.
    */
   duh = lib.dumb_read_any(df, 0, 0);
#else
   duh = loader(df);
#endif
   if (!duh) {
      ALLEGRO_ERROR("Failed to create DUH.\n");
      goto Error;
   }

   sig = lib.duh_start_sigrenderer(duh, 0, 2, 0);
   if (!sig) {
      ALLEGRO_ERROR("duh_start_sigrenderer failed.\n");
      goto Error;
   }

   it_sig = lib.duh_get_it_sigrenderer(sig);
   if (it_sig) {
      /* Turn off freezing for XM files. Seems completely pointless. */
      lib.dumb_it_set_xm_speed_zero_callback(it_sig, lib.dumb_it_callback_terminate, NULL);
   }

   stream = al_create_audio_stream(buffer_count, samples, 44100,
      ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);

   if (stream) {
      MOD_FILE *mf = al_malloc(sizeof(MOD_FILE));
      mf->duh = duh;
      mf->sig = sig;
      mf->fh = NULL;
      mf->length = lib.duh_get_length(duh) / 65536.0;
      if (mf->length < 0)
         mf->length = 0;
      mf->loop_start = -1;
      mf->loop_end = -1;

      stream->extra = mf;
      stream->feeder = modaudio_stream_update;
      stream->unload_feeder = modaudio_stream_close;
      stream->rewind_feeder = modaudio_stream_rewind;
      stream->seek_feeder = modaudio_stream_seek;
      stream->get_feeder_position = modaudio_stream_get_position;
      stream->get_feeder_length = modaudio_stream_get_length;
      stream->set_feeder_loop = modaudio_stream_set_loop;
      _al_acodec_start_feed_thread(stream);
   }
   else {
      ALLEGRO_ERROR("Failed to create stream.\n");
      goto Error;
   }

   return stream;

Error:

   if (sig) {
      lib.duh_end_sigrenderer(sig);
   }

   if (duh) {
      lib.unload_duh(duh);
   }

   /* try to return back to where we started to load */
   if (start_pos != -1)
      al_fseek(f, start_pos, ALLEGRO_SEEK_SET);

   return NULL;
}
Beispiel #6
0
static int stream_component_open(VideoState * is, int stream_index)
{

   AVFormatContext *format_context = is->format_context;
   AVCodecContext *codecCtx;
   AVCodec *codec;

   if (stream_index < 0 || stream_index >= (int)format_context->nb_streams) {
      return -1;
   }

   // Get a pointer to the codec context for the video stream
   codecCtx = format_context->streams[stream_index]->codec;


   if (codecCtx->codec_type == AVMEDIA_TYPE_AUDIO) {
      // Set audio settings from codec info
      is->video->audio =
          al_create_audio_stream(4, AUDIO_BUFFER_SIZE / 4,
                                 codecCtx->sample_rate,
                                 ALLEGRO_AUDIO_DEPTH_INT16,
                                 ALLEGRO_CHANNEL_CONF_1 + codecCtx->channels -
                                 1);

      if (!is->video->audio) {
         ALLEGRO_ERROR("al_create_audio_stream failed\n");
         return -1;
      }

      is->audio_thread = al_create_thread(stream_audio, is);
      al_start_thread(is->audio_thread);

      is->audio_hw_buf_size = AUDIO_BUFFER_SIZE;
   }
   codec = avcodec_find_decoder(codecCtx->codec_id);
   if (codec) {
      #ifdef FFMPEG_0_8
      if (avcodec_open2(codecCtx, codec, NULL) < 0) codec = NULL;
      #else
      if (avcodec_open(codecCtx, codec) < 0) codec = NULL;
      #endif
   }
   if (!codec) {
      ALLEGRO_ERROR("Unsupported codec!\n");
      return -1;
   }

   switch (codecCtx->codec_type) {
      case AVMEDIA_TYPE_AUDIO:
         is->audioStream = stream_index;
         is->audio_st = format_context->streams[stream_index];
         is->audio_buf_size = 0;
         is->audio_buf_index = 0;

         /* averaging filter for audio sync */
         is->audio_diff_avg_coef = exp(log(0.01 / AUDIO_DIFF_AVG_NB));
         is->audio_diff_avg_count = 0;
         /* Correct audio only if larger error than this */
         is->audio_diff_threshold = 0.1;

         memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
         packet_queue_init(&is->audioq);

         break;
      case AVMEDIA_TYPE_VIDEO:
         is->videoStream = stream_index;
         is->video_st = format_context->streams[stream_index];

         is->frame_timer = (double)av_gettime() / 1000000.0;
         is->frame_last_delay = 40e-3;
         is->video_current_pts_time = av_gettime();

         packet_queue_init(&is->videoq);
         is->video_thread = al_create_thread(video_thread, is);
         al_start_thread(is->video_thread);
         codecCtx->get_buffer = our_get_buffer;
         codecCtx->release_buffer = our_release_buffer;

         break;
      default:
         break;
   }

   return 0;
}
Beispiel #7
0
ALLEGRO_AUDIO_STREAM *_al_load_ogg_opus_audio_stream_f(ALLEGRO_FILE *file,
   size_t buffer_count, unsigned int samples)
{
   const int word_size = 2; /* 1 = 8bit, 2 = 16-bit. nothing else */
   OggOpusFile* of;
   int channels;
   long rate;
   long total_samples;
   long total_size;
   int bitstream;
   AL_OP_DATA* extra;
   ALLEGRO_AUDIO_STREAM* stream;

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

   extra = al_malloc(sizeof(AL_OP_DATA));
   if (extra == NULL) {
      ALLEGRO_ERROR("Failed to allocate AL_OP_DATA struct.\n");
      return NULL;
   }

   extra->file = file;

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

   extra->of = of;
   extra->bitstream = -1;
   bitstream = extra->bitstream;

   extra->channels = lib.op_channel_count(of, bitstream);
   channels = extra->channels;

   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", total_samples);
   ALLEGRO_DEBUG("total_size %ld\n", total_size);

   stream = al_create_audio_stream(buffer_count, samples, rate,
            _al_word_size_to_depth_conf(word_size),
            _al_count_to_channel_conf(channels));
   if (!stream) {
      lib.op_free(of);
      return NULL;
   }

   stream->extra = extra;

   extra->loop_start = 0.0;
   extra->loop_end = ogg_stream_get_length(stream);
   stream->quit_feed_thread = false;
   stream->feeder = ogg_stream_update;
   stream->rewind_feeder = ogg_stream_rewind;
   stream->seek_feeder = ogg_stream_seek;
   stream->get_feeder_position = ogg_stream_get_position;
   stream->get_feeder_length = ogg_stream_get_length;
   stream->set_feeder_loop = ogg_stream_set_loop;
   stream->unload_feeder = ogg_stream_close;
   _al_acodec_start_feed_thread(stream);

   return stream;
}
Beispiel #8
0
static ALLEGRO_AUDIO_STREAM *mod_stream_init(ALLEGRO_FILE* f,
   size_t buffer_count, unsigned int samples, DUH *(loader)(DUMBFILE *))
{
   ALLEGRO_AUDIO_STREAM *stream;
   DUMBFILE *df;
   DUH_SIGRENDERER *sig = NULL;
   DUH *duh = NULL;
   DUMB_IT_SIGRENDERER *it_sig = NULL;
   int64_t start_pos = -1;
   
   df = lib.dumbfile_open_ex(f, &dfs_f);
   if (!df)
      return NULL;
      
   start_pos = al_ftell(f);

   duh = loader(df);
   if (!duh) {
      goto Error;
   }

   sig = lib.duh_start_sigrenderer(duh, 0, 2, 0);
   if (!sig) {
      goto Error;
   }

   it_sig = lib.duh_get_it_sigrenderer(sig);
   if (it_sig) {
      /* Turn off freezing for XM files. Seems completely pointless. */
      lib.dumb_it_set_xm_speed_zero_callback(it_sig, lib.dumb_it_callback_terminate, NULL);
   }

   stream = al_create_audio_stream(buffer_count, samples, 44100,
      ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2); 

   if (stream) {
      MOD_FILE *mf = al_malloc(sizeof(MOD_FILE));
      mf->duh = duh;
      mf->sig = sig;
      mf->fh = NULL;
      mf->length = lib.duh_get_length(duh) / 65536.0;
      if (mf->length < 0)
         mf->length = 0;
      mf->loop_start = -1;
      mf->loop_end = -1;

      stream->extra = mf;
      stream->feeder = modaudio_stream_update;
      stream->unload_feeder = modaudio_stream_close;
      stream->rewind_feeder = modaudio_stream_rewind;
      stream->seek_feeder = modaudio_stream_seek;
      stream->get_feeder_position = modaudio_stream_get_position;
      stream->get_feeder_length = modaudio_stream_get_length;
      stream->set_feeder_loop = modaudio_stream_set_loop;
      _al_acodec_start_feed_thread(stream);
   }
   else {
      goto Error;
   }

   return stream;

Error:

   if (sig) {
      lib.duh_end_sigrenderer(sig);
   }

   if (duh) {
      lib.unload_duh(duh);
   }

   /* try to return back to where we started to load */
   if (start_pos != -1)
      al_fseek(f, start_pos, ALLEGRO_SEEK_SET);

   return NULL;
}
/* return the player so you can use more advanced features if you want
   you can safely ignore the return value if all you want is to play a mod */
DUMBA5_PLAYER * dumba5_create_player(DUH * dp, int pattern, bool loop, int bufsize, int frequency, bool stereo)
{
	DUMBA5_PLAYER * player;
	ALLEGRO_CHANNEL_CONF c_conf;
	int n_channels = 2;

	/* This restriction is imposed by Allegro. */
	ASSERT(n_channels > 0);
	ASSERT(n_channels <= 2);
	
	if(!dp)
	{
		return NULL;
	}

	player = (DUMBA5_PLAYER *) malloc(sizeof(DUMBA5_PLAYER));
	if(!player)
	{
		return NULL;
	}

	player->flags = 0;
	player->bufsize = bufsize;
	player->freq = frequency;
	player->channels = n_channels;
	if(n_channels == 1)
	{
		c_conf = ALLEGRO_CHANNEL_CONF_1;
	}
	else
	{
		c_conf = ALLEGRO_CHANNEL_CONF_2;
	}

	player->stream = al_create_audio_stream(4, bufsize, frequency, ALLEGRO_AUDIO_DEPTH_INT16, c_conf);

	if(!player->stream)
	{
		free(player);
		return NULL;
	}
	al_attach_audio_stream_to_mixer(player->stream, al_get_default_mixer());

	player->sigrenderer = dumb_it_start_at_order(dp, n_channels, pattern);

	if(!player->sigrenderer)
	{
		al_destroy_audio_stream(player->stream);
		free(player);
		return NULL;
	}
	player->mutex = al_create_mutex();
	if(!player->mutex)
	{
		return NULL;
	}
	player->thread = al_create_thread(dumba5_update_thread, player);
	if(!player->thread)
	{
		return NULL;
	}

	player->volume = 1.0;
	player->silentcount = 0;
	player->duh = dp;

	return player;
}
DUMBA5_PLAYER * dumba5_start_duh_x(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq)
{
	DUMBA5_PLAYER * dp;
	ALLEGRO_CHANNEL_CONF c_conf;

	/* This restriction is imposed by Allegro. */
	ASSERT(n_channels > 0);
	ASSERT(n_channels <= 2);
	
	if(!duh)
	{
		return NULL;
	}

	dp = (DUMBA5_PLAYER *) malloc(sizeof(DUMBA5_PLAYER));
	if(!dp)
	{
		return NULL;
	}

	dp->flags = ADP_PLAYING;
	dp->bufsize = bufsize;
	dp->freq = freq;
	dp->channels = n_channels;
	if(n_channels == 1)
	{
		c_conf = ALLEGRO_CHANNEL_CONF_1;
	}
	else
	{
		c_conf = ALLEGRO_CHANNEL_CONF_2;
	}

	dp->stream = al_create_audio_stream(4, bufsize, freq, ALLEGRO_AUDIO_DEPTH_INT16, c_conf);

	if (!dp->stream) {
		free(dp);
		return NULL;
	}
	al_attach_audio_stream_to_mixer(dp->stream, al_get_default_mixer());

	dp->sigrenderer = dumb_it_start_at_order(duh, n_channels, pos);

	if (!dp->sigrenderer) {
		al_destroy_audio_stream(dp->stream);
		free(dp);
		return NULL;
	}
	dp->thread = al_create_thread(dumba5_update_thread, dp);
	if(!dp->thread)
	{
		return NULL;
	}

	dp->volume = volume;
	dp->silentcount = 0;
	dp->duh = duh;
	al_start_thread(dp->thread);

	return dp;
}
Beispiel #11
0
int main(int argc, char *argv[])
{
   ALLEGRO_DISPLAY *display;
   (void)argc;
   (void)argv;

   if (!al_init()) {
      abort_example("Could not init Allegro.\n");
   }

   open_log();

   al_install_keyboard();
   al_install_mouse();

   al_init_primitives_addon();
   al_init_font_addon();
   al_init_ttf_addon();

   al_set_new_display_flags(ALLEGRO_GENERATE_EXPOSE_EVENTS);
   display = al_create_display(800, 600);
   if (!display) {
      abort_example("Unable to create display\n");
   }
   al_set_window_title(display, "Synthesiser of sorts");

   font_gui = al_load_ttf_font("data/DejaVuSans.ttf", 12, 0);
   if (!font_gui) {
      abort_example("Failed to load data/fixed_font.tga\n");
   }

   if (!al_install_audio()) {
      abort_example("Could not init sound!\n");
   }

   if (!al_reserve_samples(0)) {
      abort_example("Could not set up voice and mixer.\n");
   }

   size_t buffers = 8;
   unsigned samples = SAMPLES_PER_BUFFER;
   unsigned freq = STREAM_FREQUENCY;
   ALLEGRO_AUDIO_DEPTH depth = ALLEGRO_AUDIO_DEPTH_FLOAT32;
   ALLEGRO_CHANNEL_CONF ch = ALLEGRO_CHANNEL_CONF_1;

   stream1 = al_create_audio_stream(buffers, samples, freq, depth, ch);
   stream2 = al_create_audio_stream(buffers, samples, freq, depth, ch);
   stream3 = al_create_audio_stream(buffers, samples, freq, depth, ch);
   stream4 = al_create_audio_stream(buffers, samples, freq, depth, ch);
   stream5 = al_create_audio_stream(buffers, samples, freq, depth, ch);
   if (!stream1 || !stream2 || !stream3 || !stream4 || !stream5) {
      abort_example("Could not create stream.\n");
   }

   ALLEGRO_MIXER *mixer = al_get_default_mixer();
   if (
      !al_attach_audio_stream_to_mixer(stream1, mixer) ||
      !al_attach_audio_stream_to_mixer(stream2, mixer) ||
      !al_attach_audio_stream_to_mixer(stream3, mixer) ||
      !al_attach_audio_stream_to_mixer(stream4, mixer) ||
      !al_attach_audio_stream_to_mixer(stream5, mixer)
   ) {
      abort_example("Could not attach stream to mixer.\n");
   }

   al_set_mixer_postprocess_callback(mixer, mixer_pp_callback, mixer);

   /* Prog is destroyed at the end of this scope. */
   {
      Theme theme(font_gui);
      Prog prog(theme, display);
      prog.run();
   }

   al_destroy_audio_stream(stream1);
   al_destroy_audio_stream(stream2);
   al_destroy_audio_stream(stream3);
   al_destroy_audio_stream(stream4);
   al_destroy_audio_stream(stream5);
   al_uninstall_audio();

   al_destroy_font(font_gui);

   al_fclose(save_fp);

   close_log(false);

   return 0;
}
static void mainloop(void)
{
   ALLEGRO_EVENT_QUEUE *queue;
   ALLEGRO_TIMER *timer;
   float *buf;
   double pitch = 440;
   int i, si;
   int n = 0;
   bool redraw = false;
   
   for (i = 0; i < N; i++) {
      frequency[i] = 22050 * pow(2, i / (double)N);
      stream[i] = al_create_audio_stream(4, SAMPLES_PER_BUFFER, frequency[i],
         ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_1);
      if (!stream[i]) {
         abort_example("Could not create stream.\n");
         return;
      }

      if (!al_attach_audio_stream_to_mixer(stream[i], al_get_default_mixer())) {
         abort_example("Could not attach stream to mixer.\n");
         return;
      }
   }

   queue = al_create_event_queue();
   al_register_event_source(queue, al_get_keyboard_event_source());
   for (i = 0; i < N; i++) {
      al_register_event_source(queue,
         al_get_audio_stream_event_source(stream[i]));
   }
#ifdef ALLEGRO_POPUP_EXAMPLES
   if (textlog) {
      al_register_event_source(queue, al_get_native_text_log_event_source(textlog));
   }
#endif

   log_printf("Generating %d sine waves of different sampling quality\n", N);
   log_printf("If Allegro's resampling is correct there should be little variation\n", N);

   timer = al_create_timer(1.0 / 60);
   al_register_event_source(queue, al_get_timer_event_source(timer));
   
   al_register_event_source(queue, al_get_display_event_source(display));

   al_start_timer(timer);
   while (n < 60 * frequency[0] / SAMPLES_PER_BUFFER * N) {
      ALLEGRO_EVENT event;

      al_wait_for_event(queue, &event);

      if (event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT) {
         for (si = 0; si < N; si++) {
            buf = al_get_audio_stream_fragment(stream[si]);
            if (!buf) {
               continue;
            }

            for (i = 0; i < SAMPLES_PER_BUFFER; i++) {
               double t = samplepos[si]++ / (double)frequency[si];
               buf[i] = sin(t * pitch * ALLEGRO_PI * 2) / N;
            }

            if (!al_set_audio_stream_fragment(stream[si], buf)) {
               log_printf("Error setting stream fragment.\n");
            }

            n++;
            log_printf("%d", si);
            if ((n % 60) == 0)
               log_printf("\n");
         }
      }
      
      if (event.type == ALLEGRO_EVENT_TIMER) {
         redraw = true;
      }

      if (event.type == ALLEGRO_EVENT_KEY_DOWN &&
            event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
         break;
      }

      if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
         break;
      }

#ifdef ALLEGRO_POPUP_EXAMPLES
      if (event.type == ALLEGRO_EVENT_NATIVE_DIALOG_CLOSE) {
         break;
      }
#endif

      if (redraw &&al_is_event_queue_empty(queue)) {
         ALLEGRO_COLOR c = al_map_rgb(0, 0, 0);
         int i;
         al_clear_to_color(al_map_rgb_f(1, 1, 1));
        
         for (i = 0; i < 640; i++) {
            al_draw_pixel(i, 50 + waveform[i] * 50, c);
         }

         al_flip_display();
         redraw = false;
      }
   }

   for (si = 0; si < N; si++) {
      al_drain_audio_stream(stream[si]);
   }

   log_printf("\n");

   al_destroy_event_queue(queue);
}
Beispiel #13
0
int main(int argc, char **argv)
{
   ALLEGRO_AUDIO_RECORDER *r;
   ALLEGRO_AUDIO_STREAM *s;
   
   ALLEGRO_EVENT_QUEUE *q;
   ALLEGRO_DISPLAY *d;
   ALLEGRO_FILE *fp = NULL;
   ALLEGRO_PATH *tmp_path = NULL;
      
   int prev = 0;
   bool is_recording = false;
   
   int n = 0; /* number of samples written to disk */
   
   (void) argc;
   (void) argv;

   if (!al_init()) {
      abort_example("Could not init Allegro.\n");
   }
   
   if (!al_init_primitives_addon()) {
      abort_example("Unable to initialize primitives addon");
   }
      
   if (!al_install_keyboard()) {
      abort_example("Unable to install keyboard");
   }
      
   if (!al_install_audio()) {
      abort_example("Unable to initialize audio addon");
   }
   
   if (!al_init_acodec_addon()) {
      abort_example("Unable to initialize acodec addon");
   }
   
   /* Note: increasing the number of channels will break this demo. Other
    * settings can be changed by modifying the constants at the top of the
    * file.
    */
   r = al_create_audio_recorder(1000, samples_per_fragment, frequency,
      audio_depth, ALLEGRO_CHANNEL_CONF_1);
   if (!r) {
      abort_example("Unable to create audio recorder");
   }
   
   s = al_create_audio_stream(playback_fragment_count,
      playback_samples_per_fragment, frequency, audio_depth,
      ALLEGRO_CHANNEL_CONF_1);      
   if (!s) {
      abort_example("Unable to create audio stream");
   }
      
   al_reserve_samples(0);
   al_set_audio_stream_playing(s, false);
   al_attach_audio_stream_to_mixer(s, al_get_default_mixer());
      
   q = al_create_event_queue();
   
   /* Note: the following two options are referring to pixel samples, and have
    * nothing to do with audio samples. */
   al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
   al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST);
   
   d = al_create_display(320, 256);
   if (!d) {
      abort_example("Error creating display\n");
   }
      
   al_set_window_title(d, "SPACE to record. P to playback.");
   
   al_register_event_source(q, al_get_audio_recorder_event_source(r));
   al_register_event_source(q, al_get_audio_stream_event_source(s));
   al_register_event_source(q, al_get_display_event_source(d));
   al_register_event_source(q, al_get_keyboard_event_source());
   
   al_start_audio_recorder(r);
   
   while (true) {
      ALLEGRO_EVENT e;

      al_wait_for_event(q, &e);
       
      if (e.type == ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT) {
         /* We received an incoming fragment from the microphone. In this
          * example, the recorder is constantly recording even when we aren't
          * saving to disk. The display is updated every time a new fragment
          * comes in, because it makes things more simple. If the fragments
          * are coming in faster than we can update the screen, then it will be
          * a problem.
          */          
         ALLEGRO_AUDIO_RECORDER_EVENT *re = al_get_audio_recorder_event(&e);
         audio_buffer_t input = (audio_buffer_t) re->buffer;
         int sample_count = re->samples; 
         const int R = sample_count / 320;
         int i, gain = 0;
         
         /* Calculate the volume, and display it regardless if we are actively
          * recording to disk. */
         for (i = 0; i < sample_count; ++i) {
            if (gain < abs(input[i] - sample_center))
               gain = abs(input[i] - sample_center);
         }
        
         al_clear_to_color(al_map_rgb(0,0,0));
        
         if (is_recording) {
            /* Save raw bytes to disk. Assumes everything is written
             * succesfully. */
            if (fp && n < frequency / (float) samples_per_fragment * 
               max_seconds_to_record) {
               al_fwrite(fp, input, sample_count * sample_size);
               ++n;
            }

            /* Draw a pathetic visualization. It draws exactly one fragment
             * per frame. This means the visualization is dependent on the 
             * various parameters. A more thorough implementation would use this
             * event to copy the new data into a circular buffer that holds a
             * few seconds of audio. The graphics routine could then always
             * draw that last second of audio, which would cause the
             * visualization to appear constant across all different settings.
             */
            for (i = 0; i < 320; ++i) {
               int j, c = 0;
               
               /* Take the average of R samples so it fits on the screen */
               for (j = i * R; j < i * R + R && j < sample_count; ++j) {
                  c += input[j] - sample_center;
               }
               c /= R;
               
               /* Draws a line from the previous sample point to the next */
               al_draw_line(i - 1, 128 + ((prev - min_sample_val) /
                  (float) sample_range) * 256 - 128, i, 128 +
                  ((c - min_sample_val) / (float) sample_range) * 256 - 128,
                  al_map_rgb(255,255,255), 1.2);
               
               prev = c;
            }
         }
         
         /* draw volume bar */
         al_draw_filled_rectangle((gain / (float) max_sample_val) * 320, 251,
            0, 256, al_map_rgba(0, 255, 0, 128));
            
         al_flip_display();
      }
      else if (e.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT) {
         /* This event is received when we are playing back the audio clip.
          * See ex_saw.c for an example dedicated to playing streams.
          */
         if (fp) {
            audio_buffer_t output = al_get_audio_stream_fragment(s);
            if (output) {
               /* Fill the buffer from the data we have recorded into the file.
                * If an error occurs (or end of file) then silence out the
                * remainder of the buffer and stop the playback.
                */
               const size_t bytes_to_read =
                  playback_samples_per_fragment * sample_size;
               size_t bytes_read = 0, i;
               
               do {
                  bytes_read += al_fread(fp, (uint8_t *)output + bytes_read,
                     bytes_to_read - bytes_read);                  
               } while (bytes_read < bytes_to_read && !al_feof(fp) &&
                  !al_ferror(fp));
               
               /* silence out unused part of buffer (end of file) */
               for (i = bytes_read / sample_size;
                  i < bytes_to_read / sample_size; ++i) {
                     output[i] = sample_center;
               }
               
               al_set_audio_stream_fragment(s, output);
               
               if (al_ferror(fp) || al_feof(fp)) {
                  al_drain_audio_stream(s);
                  al_fclose(fp);
                  fp = NULL;
               }
            }
         }
      }      
      else if (e.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
         break;
      }
      else if (e.type == ALLEGRO_EVENT_KEY_CHAR) {
         if (e.keyboard.unichar == 27) {
            /* pressed ESC */
            break;
         }
         else if (e.keyboard.unichar == ' ') {
            if (!is_recording) {
               /* Start the recording */
               is_recording = true;
               
               if (al_get_audio_stream_playing(s)) {
                  al_drain_audio_stream(s);
               }
               
               /* Reuse the same temp file for all recordings */
               if (!tmp_path) {
                  fp = al_make_temp_file("alrecXXX.raw", &tmp_path);
               }
               else {
                  if (fp) al_fclose(fp);
                  fp = al_fopen(al_path_cstr(tmp_path, '/'), "w");
               }
               
               n = 0;
            }
            else {
               is_recording = false;
               if (fp) {
                  al_fclose(fp);
                  fp = NULL;
               }
            }
         }
         else if (e.keyboard.unichar == 'p') {
            /* Play the previously recorded wav file */
            if (!is_recording) {
               if (tmp_path) {
                  fp = al_fopen(al_path_cstr(tmp_path, '/'), "r");
                  if (fp) {
                     al_set_audio_stream_playing(s, true);
                  }
               }
            }
         }
      }
   }
   
   /* clean up */
   al_destroy_audio_recorder(r);
   al_destroy_audio_stream(s);
      
   if (fp)
      al_fclose(fp);
      
   if (tmp_path) {
      al_remove_filename(al_path_cstr(tmp_path, '/'));
      al_destroy_path(tmp_path);
   }
   
   return 0;
}