コード例 #1
0
/*
 * new_fluid_sndmgr_audio_driver
 * This implementation used the 16bit format.
 */
fluid_audio_driver_t*
new_fluid_sndmgr_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
  fluid_sndmgr_audio_driver_t* dev = NULL;
  int period_size, periods, buffer_size;

  /* check the format */
  if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
    FLUID_LOG(FLUID_ERR, "Unhandled sample format");
    return NULL;
  }

  /* compute buffer size */
  fluid_settings_getint(settings, "audio.period-size", &period_size);
  fluid_settings_getint(settings, "audio.periods", &periods);
  buffer_size = period_size*periods;

  /* allocated dev */
  dev = FLUID_NEW(fluid_sndmgr_audio_driver_t);
  if (dev == NULL) {
    FLUID_LOG(FLUID_PANIC, "Out of memory");
    return NULL;
  }
  FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t));

  dev->callback_is_audio_func = false;
  dev->data = (void *)synth;
  dev->callback = NULL;

  if (start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0) {
    delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t*)dev);
    return NULL;
  }
  return (fluid_audio_driver_t*)dev;
}
コード例 #2
0
ファイル: fluid_midi.c プロジェクト: caomw/fluidsynth
/**
 * Create a new MIDI player.
 * @param synth Fluid synthesizer instance to create player for
 * @return New MIDI player instance or NULL on error (out of memory)
 */
fluid_player_t* new_fluid_player(fluid_synth_t* synth)
{
	int i;
	fluid_player_t* player;
	player = FLUID_NEW(fluid_player_t);
	if (player == NULL) {
		FLUID_LOG(FLUID_ERR, "Out of memory");
		return NULL;
	}
	player->status = FLUID_PLAYER_READY;
	player->loop = 1;
	player->ntracks = 0;
	for (i = 0; i < MAX_NUMBER_OF_TRACKS; i++) {
		player->track[i] = NULL;
	}
	player->synth = synth;
	player->system_timer = NULL;
	player->sample_timer = NULL;
	player->playlist = NULL;
	player->currentfile = NULL;
	player->division = 0;
	player->send_program_change = 1;
	player->miditempo = 480000;
	player->deltatime = 4.0;
	player->cur_msec = 0;
	player->cur_ticks = 0;

	player->use_system_timer = 
		fluid_settings_str_equal(synth->settings, "player.timing-source", "system");

	fluid_settings_getint (synth->settings, "player.reset-synth", &i);
	player->reset_synth_between_songs = i;

	return player;
}
コード例 #3
0
ファイル: fluidsynth.c プロジェクト: caomw/fluidsynth
/*
 * main
 */
int main(int argc, char** argv)
{
  fluid_settings_t* settings;
  int arg1 = 1;
  char buf[512];
  int c, i;
  int interactive = 1;
  int midi_in = 1;
  fluid_player_t* player = NULL;
  fluid_midi_router_t* router = NULL;
  //fluid_sequencer_t* sequencer = NULL;
  fluid_midi_driver_t* mdriver = NULL;
  fluid_audio_driver_t* adriver = NULL;
  fluid_synth_t* synth = NULL;
  fluid_server_t* server = NULL;
  char* config_file = NULL;
  int audio_groups = 0;
  int audio_channels = 0;
  int with_server = 0;
  int dump = 0;
  int fast_render = 0;
  int connect_lash = 1;
  char *optchars = "a:C:c:dE:f:F:G:g:hijK:L:lm:nO:o:p:R:r:sT:Vvz:";
#ifdef LASH_ENABLED
  int enabled_lash = 0;		/* set to TRUE if lash gets enabled */
  fluid_lash_args_t *lash_args;

  lash_args = fluid_lash_extract_args (&argc, &argv);
#endif

  print_welcome ();

  settings = new_fluid_settings();

#ifdef GETOPT_SUPPORT	/* pre section of GETOPT supported argument handling */
  opterr = 0;

  while (1) {
    int option_index = 0;

    static struct option long_options[] = {
      {"audio-bufcount", 1, 0, 'c'},
      {"audio-bufsize", 1, 0, 'z'},
      {"audio-channels", 1, 0, 'L'},
      {"audio-driver", 1, 0, 'a'},
      {"audio-file-endian", 1, 0, 'E'},
      {"audio-file-format", 1, 0, 'O'},
      {"audio-file-type", 1, 0, 'T'},
      {"audio-groups", 1, 0, 'G'},
      {"chorus", 1, 0, 'C'},
      {"connect-jack-outputs", 0, 0, 'j'},
      {"disable-lash", 0, 0, 'l'},
      {"dump", 0, 0, 'd'},
      {"fast-render", 1, 0, 'F'},
      {"gain", 1, 0, 'g'},
      {"help", 0, 0, 'h'},
      {"load-config", 1, 0, 'f'},
      {"midi-channels", 1, 0, 'K'},
      {"midi-driver", 1, 0, 'm'},
      {"no-midi-in", 0, 0, 'n'},
      {"no-shell", 0, 0, 'i'},
      {"option", 1, 0, 'o'},
      {"portname", 1, 0, 'p'},
      {"reverb", 1, 0, 'R'},
      {"sample-rate", 1, 0, 'r'},
      {"server", 0, 0, 's'},
      {"verbose", 0, 0, 'v'},
      {"version", 0, 0, 'V'},
      {0, 0, 0, 0}
    };

    c = getopt_long(argc, argv, optchars, long_options, &option_index);
    if (c == -1) {
      break;
    }
#else	/* "pre" section to non getopt argument handling */
  for (i = 1; i < argc; i++) {
    char *optarg;

    /* Skip non switch arguments (assume they are file names) */
    if ((argv[i][0] != '-') || (argv[i][1] == '\0')) break;

    c = argv[i][1];

    optarg = strchr (optchars, c);	/* find the option character in optchars */
    if (optarg && optarg[1] == ':')	/* colon follows if switch argument expected */
    {
      if (++i >= argc)
      {
	printf ("Option -%c requires an argument\n", c);
	print_usage();
	exit(0);
      }
      else
      {
	optarg = argv[i];
	if (optarg[0] == '-')
	{
	  printf ("Expected argument to option -%c found switch instead\n", c);
	  print_usage();
	  exit(0);
	}
      }
    }
    else optarg = "";
#endif

    switch (c) {
#ifdef GETOPT_SUPPORT
    case 0:	/* shouldn't normally happen, a long option's flag is set to NULL */
      printf ("option %s", long_options[option_index].name);
      if (optarg) {
	printf (" with arg %s", optarg);
      }
      printf ("\n");
      break;
#endif
    case 'a':
      if (FLUID_STRCMP (optarg, "help") == 0)
      {
        printf ("-a options (audio driver):\n   ");
        show_settings_str_options (settings, "audio.driver");
        exit (0);
      }
      else fluid_settings_setstr(settings, "audio.driver", optarg);
      break;
    case 'C':
      if ((optarg != NULL) && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "no") == 0))) {
	fluid_settings_setint(settings, "synth.chorus.active", FALSE);
      } else {
	fluid_settings_setint(settings, "synth.chorus.active", TRUE);
      }
      break;
    case 'c':
      fluid_settings_setint(settings, "audio.periods", atoi(optarg));
      break;
    case 'd':
      fluid_settings_setint(settings, "synth.dump", TRUE);
      dump = 1;
      break;
    case 'E':
      if (FLUID_STRCMP (optarg, "help") == 0)
      {
        printf ("-E options (audio file byte order):\n   ");
        show_settings_str_options (settings, "audio.file.endian");

#if LIBSNDFILE_SUPPORT
        printf ("\nauto: Use audio file format's default endian byte order\n"
                "cpu: Use CPU native byte order\n");
#else
        printf ("\nNOTE: No libsndfile support!\n"
                "cpu: Use CPU native byte order\n");
#endif
        exit (0);
      }
      else fluid_settings_setstr(settings, "audio.file.endian", optarg);
      break;
    case 'f':
      config_file = optarg;
      break;
    case 'F':
      fluid_settings_setstr(settings, "audio.file.name", optarg);
      fast_render = 1;
      break;
    case 'G':
      audio_groups = atoi(optarg);
      break;
    case 'g':
      fluid_settings_setnum(settings, "synth.gain", atof(optarg));
      break;
    case 'h':
      print_help(settings);
      break;
    case 'i':
      interactive = 0;
      break;
    case 'j':
      fluid_settings_setint(settings, "audio.jack.autoconnect", 1);
      break;
    case 'K':
      fluid_settings_setint(settings, "synth.midi-channels", atoi(optarg));
      break;
    case 'L':
      audio_channels = atoi(optarg);
      fluid_settings_setint(settings, "synth.audio-channels", audio_channels);
      break;
    case 'l':			/* disable LASH */
      connect_lash = 0;
      break;
    case 'm':
      if (FLUID_STRCMP (optarg, "help") == 0)
      {
        printf ("-m options (MIDI driver):\n   ");
        show_settings_str_options (settings, "midi.driver");
        exit (0);
      }
      else fluid_settings_setstr(settings, "midi.driver", optarg);
      break;
    case 'n':
      midi_in = 0;
      break;
    case 'O':
      if (FLUID_STRCMP (optarg, "help") == 0)
      {
        printf ("-O options (audio file format):\n   ");
        show_settings_str_options (settings, "audio.file.format");

#if LIBSNDFILE_SUPPORT
        printf ("\ns8, s16, s24, s32: Signed PCM audio of the given number of bits\n");
        printf ("float, double: 32 bit and 64 bit floating point audio\n");
        printf ("u8: Unsigned 8 bit audio\n");
#else
        printf ("\nNOTE: No libsndfile support!\n");
#endif
        exit (0);
      }
      else fluid_settings_setstr(settings, "audio.file.format", optarg);
      break;
    case 'o':
      process_o_cmd_line_option(settings, optarg);
      break;
    case 'p' :
      fluid_settings_setstr(settings, "midi.portname", optarg);
      break;
    case 'R':
      if ((optarg != NULL) && ((strcmp(optarg, "0") == 0) || (strcmp(optarg, "no") == 0))) {
	fluid_settings_setint(settings, "synth.reverb.active", FALSE);
      } else {
	fluid_settings_setint(settings, "synth.reverb.active", TRUE);
      }
      break;
    case 'r':
      fluid_settings_setnum(settings, "synth.sample-rate", atof(optarg));
      break;
    case 's':
      with_server = 1;
      break;
    case 'T':
      if (FLUID_STRCMP (optarg, "help") == 0)
      {
        printf ("-T options (audio file type):\n   ");
        show_settings_str_options (settings, "audio.file.type");

#if LIBSNDFILE_SUPPORT
        printf ("\nauto: Determine type from file name extension, defaults to \"wav\"\n");
#else
        printf ("\nNOTE: No libsndfile support!\n");
#endif
        exit (0);
      }
      else fluid_settings_setstr(settings, "audio.file.type", optarg);
      break;
    case 'V':
      printf("FluidSynth %s\n", VERSION);
      exit (0);
      break;
    case 'v':
      fluid_settings_setint(settings, "synth.verbose", TRUE);
      break;
    case 'z':
      fluid_settings_setint(settings, "audio.period-size", atoi(optarg));
      break;
#ifdef GETOPT_SUPPORT
    case '?':
      printf ("Unknown option %c\n", optopt);
      print_usage();
      exit(0);
      break;
    default:
      printf ("?? getopt returned character code 0%o ??\n", c);
      break;
#else			/* Non getopt default case */
    default:
      printf ("Unknown switch '%c'\n", c);
      print_usage();
      exit(0);
      break;
#endif
    }	/* end of switch statement */
  }	/* end of loop */

#ifdef GETOPT_SUPPORT
  arg1 = optind;
#else
  arg1 = i;
#endif

  /* option help requested?  "-o help" */
  if (option_help)
  {
    printf ("FluidSynth settings:\n");
    fluid_settings_foreach (settings, settings, settings_foreach_func);
    exit (0);
  }

#ifdef WIN32
  SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
#endif

#ifdef LASH_ENABLED
  /* connect to the lash server */
  if (connect_lash)
    {
      enabled_lash = fluid_lash_connect (lash_args);
      fluid_settings_setint (settings, "lash.enable", enabled_lash ? 1 : 0);
    }
#endif

  /* The 'groups' setting is only relevant for LADSPA operation
   * If not given, set number groups to number of audio channels, because
   * they are the same (there is nothing between synth output and 'sound card')
   */
  if ((audio_groups == 0) && (audio_channels != 0)) {
      audio_groups = audio_channels;
  }
  fluid_settings_setint(settings, "synth.audio-groups", audio_groups);

  if (fast_render) {
    midi_in = 0;
    interactive = 0;
    with_server = 0;
    fluid_settings_setstr(settings, "player.timing-source", "sample");  
    fluid_settings_setint(settings, "synth.parallel-render", 1); /* TODO: Fast_render should not need this, but currently do */
  }
  
  /* create the synthesizer */
  synth = new_fluid_synth(settings);
  if (synth == NULL) {
    fprintf(stderr, "Failed to create the synthesizer\n");
    exit(-1);
  }

  cmd_handler = new_fluid_cmd_handler(synth);
  if (cmd_handler == NULL) {
    fprintf(stderr, "Failed to create the command handler\n");
    goto cleanup;
  }

  /* load the soundfonts (check that all non options are SoundFont or MIDI files) */
  for (i = arg1; i < argc; i++) {
    if (fluid_is_soundfont(argv[i]))
    {
      if (fluid_synth_sfload(synth, argv[i], 1) == -1)
	fprintf(stderr, "Failed to load the SoundFont %s\n", argv[i]);
    }
    else if (!fluid_is_midifile(argv[i]))
      fprintf (stderr, "Parameter '%s' not a SoundFont or MIDI file or error occurred identifying it.\n",
	       argv[i]);
  }

#ifdef HAVE_SIGNAL_H
/*   signal(SIGINT, handle_signal); */
#endif

  /* start the synthesis thread */
  if (!fast_render) {
    adriver = new_fluid_audio_driver(settings, synth);
    if (adriver == NULL) {
      fprintf(stderr, "Failed to create the audio driver\n");
      goto cleanup;
    }
  }


  /* start the midi router and link it to the synth */
#if WITH_MIDI
  if (midi_in) {
    /* In dump mode, text output is generated for events going into and out of the router.
     * The example dump functions are put into the chain before and after the router..
     */
    //sequencer = new_fluid_sequencer2(0);

    router = new_fluid_midi_router(
      settings,
      dump ? fluid_midi_dump_postrouter : fluid_synth_handle_midi_event,
      (void*)synth);

    if (router == NULL) {
      fprintf(stderr, "Failed to create the MIDI input router; no MIDI input\n"
	      "will be available. You can access the synthesizer \n"
	      "through the console.\n");
    } else {
      fluid_synth_set_midi_router(synth, router); /* Fixme, needed for command handler */
//      fluid_sequencer_register_fluidsynth(sequencer, synth);
      mdriver = new_fluid_midi_driver(
	settings,
	dump ? fluid_midi_dump_prerouter : fluid_midi_router_handle_midi_event,
	(void*) router);
      if (mdriver == NULL) {
	fprintf(stderr, "Failed to create the MIDI thread; no MIDI input\n"
		"will be available. You can access the synthesizer \n"
		"through the console.\n");
      }
    }
  }
#endif

  /* run commands specified in config file */
  if (config_file != NULL) {
    fluid_source(cmd_handler, config_file);
  } else if (fluid_get_userconf(buf, 512) != NULL) {
    fluid_source(cmd_handler, buf);
  } else if (fluid_get_sysconf(buf, 512) != NULL) {
    fluid_source(cmd_handler, buf);
  }



  /* play the midi files, if any */
  for (i = arg1; i < argc; i++) {
    if ((argv[i][0] != '-') && fluid_is_midifile(argv[i])) {

      if (player == NULL) {
	player = new_fluid_player(synth);
	if (player == NULL) {
	  fprintf(stderr, "Failed to create the midifile player.\n"
		  "Continuing without a player.\n");
	  break;
	}
      }

      fluid_player_add(player, argv[i]);
    }
  }

  if (player != NULL) {
    fluid_player_play(player);
  }

  /* run the server, if requested */
#if !defined(MACINTOSH)
  if (with_server) {
    server = new_fluid_server(settings, newclient, synth);
    if (server == NULL) {
      fprintf(stderr, "Failed to create the server.\n"
	     "Continuing without it.\n");
    }
  }
#endif


#ifdef LASH_ENABLED
  if (enabled_lash)
    fluid_lash_create_thread (synth);
#endif

  /* run the shell */
  if (interactive) {
    printf ("Type 'help' for help topics.\n\n");

    /* In dump mode we set the prompt to "". The UI cannot easily
     * handle lines, which don't end with CR.  Changing the prompt
     * cannot be done through a command, because the current shell
     * does not handle empty arguments.  The ordinary case is dump ==
     * 0.
     */
    fluid_settings_setstr(settings, "shell.prompt", dump ? "" : "> ");
    fluid_usershell(settings, cmd_handler);
  }

  if (fast_render) {
    char *filename;
    if (player == NULL) {
      fprintf(stderr, "No midi file specified!\n");
      goto cleanup;
    } 

    fluid_settings_dupstr (settings, "audio.file.name", &filename);
    printf ("Rendering audio to file '%s'..\n", filename);
    if (filename) FLUID_FREE (filename);

    fast_render_loop(settings, synth, player);
  }

 cleanup:

#if !defined(MACINTOSH) && !defined(WIN32)
  if (server != NULL) {
    /* if the user typed 'quit' in the shell, kill the server */
    if (!interactive) {
      fluid_server_join(server);
    }
    delete_fluid_server(server);
  }
#endif

  if (cmd_handler != NULL) {
    delete_fluid_cmd_handler(cmd_handler);
  }

  if (player != NULL) {
    /* if the user typed 'quit' in the shell, stop the player */
    if (interactive) {
      fluid_player_stop(player);
    }
    if (adriver != NULL || !fluid_settings_str_equal(settings,  "player.timing-source", "sample")) {
      /* if no audio driver and sample timers are used, nothing makes the player advance */  
      fluid_player_join(player);
    }
    delete_fluid_player(player);
  }

  if (router) {
#if WITH_MIDI
    if (mdriver) {
      delete_fluid_midi_driver(mdriver);
    }
    delete_fluid_midi_router(router);
#endif
  }

  /*if (sequencer) {
    delete_fluid_sequencer(sequencer);
  }*/

  if (adriver) {
    delete_fluid_audio_driver(adriver);
  }

  if (synth) {
    delete_fluid_synth(synth);
  }

  if (settings) {
    delete_fluid_settings(settings);
  }

  return 0;
}

static fluid_cmd_handler_t* newclient(void* data, char* addr)
{
  fluid_synth_t* synth = (fluid_synth_t*) data;
  return new_fluid_cmd_handler(synth);
}
コード例 #4
0
ファイル: fluid_portaudio.c プロジェクト: caomw/fluidsynth
fluid_audio_driver_t *
new_fluid_portaudio_driver (fluid_settings_t *settings, fluid_synth_t *synth)
{
  fluid_portaudio_driver_t *dev = NULL;
  PaStreamParameters outputParams;
  char *device = NULL;
  double sample_rate;
  int period_size;
  PaError err;

  dev = FLUID_NEW (fluid_portaudio_driver_t);

  if (dev == NULL)
  {
    FLUID_LOG (FLUID_ERR, "Out of memory");
    return NULL;
  }

  err = Pa_Initialize ();

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error initializing PortAudio driver: %s",
               Pa_GetErrorText (err));
    FLUID_FREE (dev);
    return NULL;
  }

  FLUID_MEMSET (dev, 0, sizeof (fluid_portaudio_driver_t));

  dev->synth = synth;

  fluid_settings_getint (settings, "audio.period-size", &period_size);
  fluid_settings_getnum (settings, "synth.sample-rate", &sample_rate);
  fluid_settings_dupstr(settings, "audio.portaudio.device", &device);   /* ++ alloc device name */

  bzero (&outputParams, sizeof (outputParams));
  outputParams.channelCount = 2;
  outputParams.suggestedLatency = (PaTime)period_size / sample_rate;

  /* Locate the device if specified */
  if (strcmp (device, PORTAUDIO_DEFAULT_DEVICE) != 0)
  {
    const PaDeviceInfo *deviceInfo;
    int numDevices;
    int i;

    numDevices = Pa_GetDeviceCount ();

    if (numDevices < 0)
    {
      FLUID_LOG (FLUID_ERR, "PortAudio returned unexpected device count %d", numDevices);
      goto error_recovery;
    }

    for (i = 0; i < numDevices; i++)
    {
      deviceInfo = Pa_GetDeviceInfo (i);

      if (strcmp (device, deviceInfo->name) == 0)
      {
        outputParams.device = i;
        break;
      }
    }

    if (i == numDevices)
    {
      FLUID_LOG (FLUID_ERR, "PortAudio device '%s' was not found", device);
      goto error_recovery;
    }
  }
  else outputParams.device = Pa_GetDefaultOutputDevice();

  if (fluid_settings_str_equal (settings, "audio.sample-format", "16bits"))
  {
    outputParams.sampleFormat = paInt16;
    dev->read = fluid_synth_write_s16;
  }
  else if (fluid_settings_str_equal (settings, "audio.sample-format", "float"))
  {
    outputParams.sampleFormat = paFloat32;
    dev->read = fluid_synth_write_float;
  }
  else
  {
    FLUID_LOG (FLUID_ERR, "Unknown sample format");
    goto error_recovery;
  }

  /* PortAudio section */

  /* Open an audio I/O stream. */
  err = Pa_OpenStream (&dev->stream,
                       NULL,              /* Input parameters */
                       &outputParams,
                       sample_rate,
                       period_size,
                       paNoFlag,
                       fluid_portaudio_run,
                       dev);

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error opening PortAudio stream: %s",
               Pa_GetErrorText (err));
    goto error_recovery;
  }

  err = Pa_StartStream (dev->stream);

  if (err != paNoError)
  {
    FLUID_LOG (FLUID_ERR, "Error starting PortAudio stream: %s",
               Pa_GetErrorText (err));
    goto error_recovery;
  }

  if (device) FLUID_FREE (device);      /* -- free device name */
  
  return (fluid_audio_driver_t *)dev;

error_recovery:
  if (device) FLUID_FREE (device);      /* -- free device name */
  delete_fluid_portaudio_driver ((fluid_audio_driver_t *)dev);
  return NULL;
}
コード例 #5
0
fluid_audio_driver_t*
new_fluid_dart_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
    fluid_dart_audio_driver_t* dev;
    double sample_rate;
    int periods, period_size;
    UCHAR szFailedName[ 256 ];
    MCI_AMP_OPEN_PARMS AmpOpenParms;
    int i;
    ULONG rc;

    dev = FLUID_NEW(fluid_dart_audio_driver_t);
    if (dev == NULL) {
        FLUID_LOG(FLUID_ERR, "Out of memory");
        return NULL;
    }
    FLUID_MEMSET(dev, 0, sizeof(fluid_dart_audio_driver_t));

    fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
    fluid_settings_getint(settings, "audio.periods", &periods);
    fluid_settings_getint(settings, "audio.period-size", &period_size);

    /* check the format */
    if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
        FLUID_LOG(FLUID_ERR, "Unhandled sample format");
        goto error_recovery;
    }

    dev->synth = synth;
    dev->frame_size = 2 * sizeof(short);

    /* Load only once
     */
    if( m_hmodMDM == NULLHANDLE )
    {
        rc = DosLoadModule(szFailedName, sizeof(szFailedName), "MDM", &m_hmodMDM);

        if (rc != 0 ) {
            FLUID_LOG(FLUID_ERR, "Cannot load MDM.DLL for DART due to %s", szFailedName);
            goto error_recovery;
        }

        rc = DosQueryProcAddr(m_hmodMDM, 1, NULL, (PFN *)&m_pfnmciSendCommand);

        if (rc != 0 ) {
            FLUID_LOG(FLUID_ERR, "Cannot find mciSendCommand() in MDM.DLL");
            DosFreeModule(m_hmodMDM);
            m_hmodMDM = NULLHANDLE;
            goto error_recovery;
        }
    }

    /* open the mixer device
     */
    FLUID_MEMSET(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
    AmpOpenParms.usDeviceID = (USHORT)0;
    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;

    rc = m_pfnmciSendCommand(0, MCI_OPEN,
                             MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
                             (PVOID)&AmpOpenParms, 0);

    if (rc != MCIERR_SUCCESS) {
        FLUID_LOG(FLUID_ERR, "Cannot open DART, rc = %lu", rc);
        goto error_recovery;
    }

    dev->usDeviceID = AmpOpenParms.usDeviceID;

    /* Set the MixSetupParms data structure to match the requirements.
     * This is a global that is used to setup the mixer.
     */
    dev->MixSetupParms.ulBitsPerSample = BPS_16;
    dev->MixSetupParms.ulFormatTag = MCI_WAVE_FORMAT_PCM;
    dev->MixSetupParms.ulSamplesPerSec = sample_rate;
    dev->MixSetupParms.ulChannels = 2;

    /* Setup the mixer for playback of wave data
     */
    dev->MixSetupParms.ulFormatMode = MCI_PLAY;
    dev->MixSetupParms.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
    dev->MixSetupParms.pmixEvent    = fluid_dart_audio_run;

    rc = m_pfnmciSendCommand(dev->usDeviceID, MCI_MIXSETUP,
                             MCI_WAIT | MCI_MIXSETUP_INIT,
                             (PVOID)&dev->MixSetupParms, 0);

    if (rc != MCIERR_SUCCESS) {
        FLUID_LOG(FLUID_ERR, "Cannot setup DART, rc = %lu", rc);
        goto error_recovery;
    }

    /* Set up the BufferParms data structure and allocate
     * device buffers from the Amp-Mixer
     */
    dev->BufferParms.ulNumBuffers = NUM_MIX_BUFS;
    dev->BufferParms.ulBufferSize = periods * period_size * dev->frame_size;
    dev->BufferParms.pBufList = dev->MixBuffers;

    rc = m_pfnmciSendCommand(dev->usDeviceID, MCI_BUFFER,
                             MCI_WAIT | MCI_ALLOCATE_MEMORY,
                             (PVOID)&dev->BufferParms, 0);

    if ((USHORT)rc != MCIERR_SUCCESS) {
        FLUID_LOG(FLUID_ERR, "Cannot allocate memory for DART, rc = %lu", rc);
        goto error_recovery;
    }

    /* Initialize all device buffers.
     */
    for (i = 0; i < NUM_MIX_BUFS; i++) {
       FLUID_MEMSET(dev->MixBuffers[i].pBuffer, 0, dev->BufferParms.ulBufferSize);
       dev->MixBuffers[i].ulBufferLength = dev->BufferParms.ulBufferSize;
       dev->MixBuffers[i].ulFlags = 0;
       dev->MixBuffers[i].ulUserParm = (ULONG)dev;
       fluid_synth_write_s16(dev->synth, dev->MixBuffers[i].ulBufferLength / dev->frame_size,
                             dev->MixBuffers[i].pBuffer, 0, 2, dev->MixBuffers[i].pBuffer, 1, 2 );
    }

    /* Write buffers to kick off the amp mixer.
     */
    dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle,
                                 dev->MixBuffers,
                                 NUM_MIX_BUFS);

    return (fluid_audio_driver_t*) dev;

error_recovery:

    delete_fluid_dart_audio_driver((fluid_audio_driver_t*) dev);
    return NULL;
}
コード例 #6
0
ファイル: fluid_sndio.c プロジェクト: Crest/freebsd-ports
/*
 * new_fluid_sndio_audio_driver
 */
fluid_audio_driver_t*
new_fluid_sndio_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
  fluid_sndio_audio_driver_t* dev = NULL;
  double sample_rate;
  int periods, period_size;
  char* devname;
  pthread_attr_t attr;
  int err;

  dev = FLUID_NEW(fluid_sndio_audio_driver_t);
  if (dev == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }
  FLUID_MEMSET(dev, 0, sizeof(fluid_sndio_audio_driver_t));

  fluid_settings_getint(settings, "audio.periods", &periods);
  fluid_settings_getint(settings, "audio.period-size", &period_size);
  fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);

  dev->hdl = NULL;
  dev->synth = synth;
  dev->callback = NULL;
  dev->data = NULL;
  dev->cont = 1;

  if (!fluid_settings_dupstr(settings, "audio.sndio.device", &devname)) {
    devname = NULL;
  }

  dev->hdl = sio_open(devname, SIO_PLAY, 0);
  if (dev->hdl == NULL) {
    FLUID_LOG(FLUID_ERR, "sndio could not be opened for writing");
    goto error_recovery;
  }

  sio_initpar(&dev->par);

  if (fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
    dev->par.bits = 16;
    dev->par.le = SIO_LE_NATIVE;
    dev->read = fluid_synth_write_s16;
  } else {
    FLUID_LOG(FLUID_ERR, "Unknown sample format");
    goto error_recovery;
  }

  dev->par.appbufsz = period_size * periods;
  dev->par.round = period_size;

  dev->par.pchan = 2;
  dev->par.rate = sample_rate;

  if (!sio_setpar(dev->hdl, &dev->par)) {
    FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters");
    goto error_recovery;
  }

  if (!sio_getpar(dev->hdl, &dev->par)) {
    FLUID_LOG(FLUID_ERR, "Couldn't get sndio audio parameters");
    goto error_recovery;
  } else if (dev->par.pchan != 2 || dev->par.rate != sample_rate ||
      dev->par.bits != 16) {
    FLUID_LOG(FLUID_ERR, "Couldn't set sndio audio parameters as desired");
    goto error_recovery;
  }

  dev->buffer_size = dev->par.round;
  dev->buffer_byte_size = dev->par.round * dev->par.bps * dev->par.pchan;

  dev->buffer = FLUID_MALLOC(dev->buffer_byte_size);
  if (dev->buffer == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }

  if (!sio_start(dev->hdl)) {
    FLUID_LOG(FLUID_ERR, "Couldn't start sndio");
    goto error_recovery;
  }

  if (pthread_attr_init(&attr)) {
    FLUID_LOG(FLUID_ERR, "Couldn't initialize audio thread attributes");
    goto error_recovery;
  }

  err = pthread_create(&dev->thread, &attr, fluid_sndio_audio_run, (void*) dev);
  if (err) {
    FLUID_LOG(FLUID_ERR, "Couldn't create audio thread");
    goto error_recovery;
  }

  return (fluid_audio_driver_t*) dev;

error_recovery:
  delete_fluid_sndio_audio_driver((fluid_audio_driver_t*) dev);
  return NULL;
}
コード例 #7
0
ファイル: fluid_dsound.c プロジェクト: nezticle/fluidsynth
/*
 * new_fluid_dsound_audio_driver
 */
fluid_audio_driver_t*
new_fluid_dsound_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
{
  HRESULT hr;
  DSBUFFERDESC desc;
  fluid_dsound_audio_driver_t* dev = NULL;
  DSCAPS caps;
  char *buf1;
  DWORD bytes1;
  double sample_rate;
  int periods, period_size;
  fluid_dsound_devsel_t devsel;

  /* check if the globals are initialized */
  if (FLUID_HINSTANCE == NULL) {
    FLUID_LOG(FLUID_ERR, "FluidSynth hinstance not set, which is needed for DirectSound");
    return NULL;
  }

/*
  if (fluid_wnd == NULL) {
    if (fluid_win32_create_window() != 0) {
      FLUID_LOG(FLUID_ERR, "Couldn't create window needed for DirectSound");
      return NULL;
    }
  }
*/
  /* create and clear the driver data */
  dev = FLUID_NEW(fluid_dsound_audio_driver_t);
  if (dev == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    return NULL;
  }
  FLUID_MEMSET(dev, 0, sizeof(fluid_dsound_audio_driver_t));

  dev->synth = synth;
  dev->cont = 1;

  fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
  fluid_settings_getint(settings, "audio.periods", &periods);
  fluid_settings_getint(settings, "audio.period-size", &period_size);

  /* check the format */
  if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
    FLUID_LOG(FLUID_ERR, "Unhandled sample format");
    goto error_recovery;
  }

  dev->frame_size = 2 * sizeof(short);
  dev->buffer_byte_size = period_size * dev->frame_size;
  dev->queue_byte_size = periods * dev->buffer_byte_size;
  dev->write = fluid_synth_write_s16;

  /* create and initialize the buffer format */
  dev->format = (WAVEFORMATEX*) FLUID_MALLOC(sizeof(WAVEFORMATEX));
  if (dev->format == NULL) {
    FLUID_LOG(FLUID_ERR, "Out of memory");
    goto error_recovery;
  }
  ZeroMemory(dev->format, sizeof(WAVEFORMATEX));

  dev->format->wFormatTag = WAVE_FORMAT_PCM;
  dev->format->nChannels = 2;
  dev->format->wBitsPerSample = 16;
  dev->format->nSamplesPerSec = (DWORD) sample_rate;
  dev->format->nBlockAlign = (WORD) dev->frame_size;
  dev->format->nAvgBytesPerSec = dev->format->nSamplesPerSec * dev->frame_size;
  dev->format->cbSize = 0;

  devsel.devGUID = NULL;
  /* get the selected device name. if none is specified, use NULL for the default device. */
  if(fluid_settings_dupstr(settings, "audio.dsound.device", &devsel.devname) == FLUID_OK /* ++ alloc device name */
     && devsel.devname && strlen (devsel.devname) > 0) {
    /* look for the GUID of the selected device */
    DirectSoundEnumerate((LPDSENUMCALLBACK) fluid_dsound_enum_callback2, (void *)&devsel);
  }

  if (devsel.devname) FLUID_FREE (devsel.devname);      /* -- free device name */

  /* open DirectSound */
  hr = DirectSoundCreate(devsel.devGUID, &dev->direct_sound, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to create the DirectSound object");
    goto error_recovery;
  }

  hr = IDirectSound_SetCooperativeLevel(dev->direct_sound, fluid_win32_get_window(), DSSCL_PRIORITY);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to set the cooperative level");
    goto error_recovery;
  }

  caps.dwSize = sizeof(caps);
  hr = IDirectSound_GetCaps(dev->direct_sound, &caps);
  if (hr != DS_OK)  {
    FLUID_LOG(FLUID_ERR, "Failed to query the device capacities");
    goto error_recovery;
  }

  /* create primary buffer */

  ZeroMemory(&desc, sizeof(DSBUFFERDESC));
  desc.dwSize = sizeof(DSBUFFERDESC);
  desc.dwFlags = DSBCAPS_PRIMARYBUFFER;

  if (caps.dwFreeHwMixingStreamingBuffers > 0) {
    desc.dwFlags |= DSBCAPS_LOCHARDWARE;
  }

  hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->prim_buffer, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "Failed to allocate the primary buffer");
    goto error_recovery;
  }

  /* set the primary sound buffer to this format. if it fails, just
     print a warning. */
  hr = IDirectSoundBuffer_SetFormat(dev->prim_buffer, dev->format);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_WARN, "Can't set format of primary sound buffer", fluid_win32_error(hr));
  }

  /* initialize the buffer description */

  ZeroMemory(&desc, sizeof(DSBUFFERDESC));
  desc.dwSize = sizeof(DSBUFFERDESC);
  desc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2;
  desc.lpwfxFormat = dev->format;
  desc.dwBufferBytes = dev->queue_byte_size;
  desc.dwReserved = 0;

  if (caps.dwFreeHwMixingStreamingBuffers > 0) {
    desc.dwFlags |= DSBCAPS_LOCHARDWARE;
  }

  /* create the secondary sound buffer */

  hr = IDirectSound_CreateSoundBuffer(dev->direct_sound, &desc, &dev->sec_buffer, NULL);
  if (hr != DS_OK) {
    FLUID_LOG(FLUID_ERR, "dsound: Can't create sound buffer: %s", fluid_win32_error(hr));
    goto error_recovery;
  }


  /* Lock */
  hr = IDirectSoundBuffer_Lock(dev->sec_buffer, 0, 0, (void*) &buf1, &bytes1, 0, 0, DSBLOCK_ENTIREBUFFER);

  if ((hr != DS_OK) || (buf1 == NULL)) {
    FLUID_LOG(FLUID_PANIC, "Failed to lock the audio buffer. Exiting.");
    goto error_recovery;
  }

  /* fill the buffer with silence */
  memset(buf1, 0, bytes1);

  /* Unlock */
  IDirectSoundBuffer_Unlock(dev->sec_buffer, buf1, bytes1, 0, 0);


  /* start the audio thread */
  dev->thread = CreateThread(NULL, 0, &fluid_dsound_audio_run, (LPVOID) dev, 0, &dev->threadID);
  if (dev->thread == NULL) {
    goto error_recovery;
  }

  return (fluid_audio_driver_t*) dev;

 error_recovery:
  delete_fluid_dsound_audio_driver((fluid_audio_driver_t*) dev);
  return NULL;
}