/** * Thread entry point for the synthesizer. Runs until the song is stopped. * @param parm Not used. * @return Always zero. */ static int synthWorkThread(void* parm) { DENG_UNUSED(parm); DENG_ASSERT(blockBuffer != 0); byte samples[BLOCK_SIZE]; while(!workerShouldStop) { if(blockBuffer->availableForWriting() < BLOCK_SIZE) { // We should not or cannot produce samples right now, let's sleep for a while. Thread_Sleep(50); continue; } //DSFLUIDSYNTH_TRACE("Synthesizing next block using fsPlayer " << fsPlayer); // Synthesize a block of samples into our buffer. fluid_synth_write_s16(DMFluid_Synth(), BLOCK_SAMPLES, samples, 0, 2, samples, 1, 2); blockBuffer->write(samples, BLOCK_SIZE); //DSFLUIDSYNTH_TRACE("Block written."); } DSFLUIDSYNTH_TRACE("Synth worker dies."); return 0; }
void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) { #ifdef AUDIO_FORMAT_32BITS fluid_synth_write_s32(synth, AUDIO_BUF_SIZE / 16, (uint32_t *)&buf[0], 0, 2, (uint32_t *)&buf[0], 1, 2 ); #else fluid_synth_write_s16(synth, AUDIO_BUF_SIZE / 8, (uint16_t *)&buf[0], 0, 2, (uint16_t *)&buf[0], 1, 2 ); #endif transfer_callback = 1; }
static void mf_process_samples(int nframes) { sndbuf_t buf[FLUS_MAX_BUF][FLUS_CHANNELS]; int ret; ret = fluid_synth_write_s16(synth, nframes, buf, 0, 2, buf, 1, 2); if (ret != FLUID_OK) { error("MIDI: fluidsynth failed\n"); return; } pcm_running = 1; pcm_write_interleaved(buf, nframes, flus_srate, flus_format, FLUS_CHANNELS, pcm_stream); }
static LONG APIENTRY fluid_dart_audio_run( ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags ) { fluid_dart_audio_driver_t* dev=(fluid_dart_audio_driver_t*)pBuffer->ulUserParm; switch( ulFlags ) { case MIX_STREAM_ERROR | MIX_WRITE_COMPLETE: /* error occur in device */ case MIX_WRITE_COMPLETE: /* for playback */ FLUID_MEMSET(pBuffer->pBuffer, 0, pBuffer->ulBufferLength); fluid_synth_write_s16(dev->synth, pBuffer->ulBufferLength / dev->frame_size, pBuffer->pBuffer, 0, 2, pBuffer->pBuffer, 1, 2 ); dev->MixSetupParms.pmixWrite(dev->MixSetupParms.ulMixHandle, pBuffer, 1); break; } return TRUE; }
size_t load_buffer(ALuint buf) { if (is_end()) { source_.seq.reset(new_fluid_sequencer2(false), &delete_fluid_sequencer); BOOST_VERIFY(fluid_sequencer_register_fluidsynth(source_.seq.get(), source_.synth.get()) != FLUID_FAILED); BOOST_VERIFY(fluid_player_add(source_.player.get(), filename_.c_str()) != FLUID_FAILED); } data_.resize(2 * source_.sample_rate * SECOND_PER_BUFFER); if (fluid_synth_write_s16(source_.synth.get(), data_.size() / 2, &data_.front(), 0, 2, &data_.front(), 1, 2) == FLUID_FAILED) { Output::Error("synth error: %s", fluid_synth_error(source_.synth.get())); } alBufferData(buf, AL_FORMAT_STEREO16, &data_.front(), sizeof(int16_t) * data_.size(), source_.sample_rate); return data_.size() / 2; }
/* * fluid_sndmgr_callback * */ void pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer) { fluid_sndmgr_audio_driver_t* dev; signed short* buf; float* left; float* right; float v; int i, k, buffer_size; dev = (fluid_sndmgr_audio_driver_t*) doubleBuffer->dbUserInfo[0]; buf = (signed short*)doubleBuffer->dbSoundData; buffer_size = dev->bufferFrameSize; if (dev->callback_is_audio_func) { /* float API : conversion to signed short */ left = dev->convbuffers[0]; right = dev->convbuffers[1]; (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->convbuffers); for (i = 0, k = 0; i < buffer_size; i++) { v = 32767.0f * left[i]; fluid_clip(v, -32768.0f, 32767.0f); buf[k++] = (signed short) v; v = 32767.0f * right[i]; fluid_clip(v, -32768.0f, 32767.0f); buf[k++] = (signed short) v; } } else { /* let the synth do the convertion */ fluid_synth_write_s16((fluid_synth_t*)dev->data, buffer_size, buf, 0, 2, buf, 1, 2); } doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbBufferReady; doubleBuffer->dbNumFrames = buffer_size; }
static aout_buffer_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block) { block_t *p_block; decoder_sys_t *p_sys = p_dec->p_sys; aout_buffer_t *p_out = NULL; if (pp_block == NULL) return NULL; p_block = *pp_block; if (p_block == NULL) return NULL; *pp_block = NULL; if (p_block->i_pts && !date_Get (&p_sys->end_date)) date_Set (&p_sys->end_date, p_block->i_pts); else if (p_block->i_pts < date_Get (&p_sys->end_date)) { msg_Warn (p_dec, "MIDI message in the past?"); goto drop; } if (p_block->i_buffer < 1) goto drop; uint8_t channel = p_block->p_buffer[0] & 0xf; uint8_t p1 = (p_block->i_buffer > 1) ? (p_block->p_buffer[1] & 0x7f) : 0; uint8_t p2 = (p_block->i_buffer > 2) ? (p_block->p_buffer[2] & 0x7f) : 0; switch (p_block->p_buffer[0] & 0xf0) { case 0x80: fluid_synth_noteoff (p_sys->synth, channel, p1); break; case 0x90: fluid_synth_noteon (p_sys->synth, channel, p1, p2); break; case 0xB0: fluid_synth_cc (p_sys->synth, channel, p1, p2); break; case 0xC0: fluid_synth_program_change (p_sys->synth, channel, p1); break; case 0xE0: fluid_synth_pitch_bend (p_sys->synth, channel, (p1 << 7) | p2); break; } unsigned samples = (p_block->i_pts - date_Get (&p_sys->end_date)) * 441 / 10000; if (samples == 0) return NULL; p_out = decoder_NewAudioBuffer (p_dec, samples); if (p_out == NULL) goto drop; p_out->i_pts = date_Get (&p_sys->end_date ); p_out->i_length = date_Increment (&p_sys->end_date, samples) - p_out->i_pts; if (!p_sys->fixed) fluid_synth_write_float (p_sys->synth, samples, p_out->p_buffer, 0, 2, p_out->p_buffer, 1, 2); else fluid_synth_write_s16 (p_sys->synth, samples, (int16_t *)p_out->p_buffer, 0, 2, (int16_t *)p_out->p_buffer, 1, 2); drop: block_Release (p_block); return p_out; }
static void fluidsynth_file_decode(struct decoder *decoder, const char *path_fs) { char setting_sample_rate[] = "synth.sample-rate"; /* char setting_verbose[] = "synth.verbose"; char setting_yes[] = "yes"; */ fluid_settings_t *settings; fluid_synth_t *synth; fluid_player_t *player; int ret; enum decoder_command cmd; /* set up fluid settings */ settings = new_fluid_settings(); if (settings == NULL) return; fluid_settings_setnum(settings, setting_sample_rate, sample_rate); /* fluid_settings_setstr(settings, setting_verbose, setting_yes); */ /* create the fluid synth */ synth = new_fluid_synth(settings); if (synth == NULL) { delete_fluid_settings(settings); return; } ret = fluid_synth_sfload(synth, soundfont_path, true); if (ret < 0) { g_warning("fluid_synth_sfload() failed"); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* create the fluid player */ player = new_fluid_player(synth); if (player == NULL) { delete_fluid_synth(synth); delete_fluid_settings(settings); return; } ret = fluid_player_add(player, path_fs); if (ret != 0) { g_warning("fluid_player_add() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* start the player */ ret = fluid_player_play(player); if (ret != 0) { g_warning("fluid_player_play() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* initialization complete - announce the audio format to the MPD core */ struct audio_format audio_format; audio_format_init(&audio_format, sample_rate, SAMPLE_FORMAT_S16, 2); decoder_initialized(decoder, &audio_format, false, -1); while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING) { int16_t buffer[2048]; const unsigned max_frames = G_N_ELEMENTS(buffer) / 2; /* read samples from fluidsynth and send them to the MPD core */ ret = fluid_synth_write_s16(synth, max_frames, buffer, 0, 2, buffer, 1, 2); if (ret != 0) break; cmd = decoder_data(decoder, NULL, buffer, sizeof(buffer), 0); if (cmd != DECODE_COMMAND_NONE) break; } /* clean up */ fluid_player_stop(player); fluid_player_join(player); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); }
static void fluidsynth_file_decode(struct decoder *decoder, const char *path_fs) { static const struct audio_format audio_format = { .sample_rate = 48000, .bits = 16, .channels = 2, }; char setting_sample_rate[] = "synth.sample-rate"; /* char setting_verbose[] = "synth.verbose"; char setting_yes[] = "yes"; */ const char *soundfont_path; fluid_settings_t *settings; fluid_synth_t *synth; fluid_player_t *player; char *path_dup; int ret; Timer *timer; enum decoder_command cmd; soundfont_path = config_get_string("soundfont", "/usr/share/sounds/sf2/FluidR3_GM.sf2"); /* set up fluid settings */ settings = new_fluid_settings(); if (settings == NULL) return; fluid_settings_setnum(settings, setting_sample_rate, 48000); /* fluid_settings_setstr(settings, setting_verbose, setting_yes); */ /* create the fluid synth */ synth = new_fluid_synth(settings); if (synth == NULL) { delete_fluid_settings(settings); return; } ret = fluid_synth_sfload(synth, soundfont_path, true); if (ret < 0) { g_warning("fluid_synth_sfload() failed"); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* create the fluid player */ player = new_fluid_player(synth); if (player == NULL) { delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* temporarily duplicate the path_fs string, because fluidsynth wants a writable string */ path_dup = g_strdup(path_fs); ret = fluid_player_add(player, path_dup); g_free(path_dup); if (ret != 0) { g_warning("fluid_player_add() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* start the player */ ret = fluid_player_play(player); if (ret != 0) { g_warning("fluid_player_play() failed"); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); return; } /* set up a timer for synchronization; fluidsynth always decodes in real time, which forces us to synchronize */ /* XXX is there any way to switch off real-time decoding? */ timer = timer_new(&audio_format); timer_start(timer); /* initialization complete - announce the audio format to the MPD core */ decoder_initialized(decoder, &audio_format, false, -1); do { int16_t buffer[2048]; const unsigned max_frames = G_N_ELEMENTS(buffer) / 2; /* synchronize with the fluid player */ timer_add(timer, sizeof(buffer)); timer_sync(timer); /* read samples from fluidsynth and send them to the MPD core */ ret = fluid_synth_write_s16(synth, max_frames, buffer, 0, 2, buffer, 1, 2); /* XXX how do we see whether the player is done? We can't access the private attribute player->status */ if (ret != 0) break; cmd = decoder_data(decoder, NULL, buffer, sizeof(buffer), 0, 0, NULL); } while (cmd == DECODE_COMMAND_NONE); /* clean up */ timer_free(timer); fluid_player_stop(player); fluid_player_join(player); delete_fluid_player(player); delete_fluid_synth(synth); delete_fluid_settings(settings); } static struct tag * fluidsynth_tag_dup(const char *file) { struct tag *tag = tag_new(); /* to be implemented */ (void)file; return tag; } static const char *const fluidsynth_suffixes[] = { "mid", NULL }; const struct decoder_plugin fluidsynth_decoder_plugin = { .name = "fluidsynth", .init = fluidsynth_init, .file_decode = fluidsynth_file_decode, .tag_dup = fluidsynth_tag_dup, .suffixes = fluidsynth_suffixes, };
void WriteSamples(ALuint count, short *buffer) { fluid_synth_write_s16(fluidSynth, count, buffer, 0, 2, buffer, 1, 2); }
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; }
static void fluidsynth_poll(sfx_softseq_t *self, byte *dest, int count) { fluid_synth_write_s16(synth, count, dest, 0, 2, dest + 2, 0, 2); }
static aout_buffer_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block) { block_t *p_block; decoder_sys_t *p_sys = p_dec->p_sys; aout_buffer_t *p_out = NULL; if (pp_block == NULL) return NULL; p_block = *pp_block; if (p_block == NULL) return NULL; *pp_block = NULL; if (p_block->i_pts > VLC_TS_INVALID && !date_Get (&p_sys->end_date)) date_Set (&p_sys->end_date, p_block->i_pts); else if (p_block->i_pts < date_Get (&p_sys->end_date)) { msg_Warn (p_dec, "MIDI message in the past?"); goto drop; } if (p_block->i_buffer < 1) goto drop; uint8_t event = p_block->p_buffer[0]; uint8_t channel = p_block->p_buffer[0] & 0xf; event &= 0xF0; if (event == 0xF0) switch (channel) { case 0: if (p_block->p_buffer[p_block->i_buffer - 1] != 0xF7) { case 7: msg_Warn (p_dec, "fragmented SysEx not implemented"); goto drop; } fluid_synth_sysex (p_sys->synth, (char *)p_block->p_buffer + 1, p_block->i_buffer - 2, NULL, NULL, NULL, 0); break; case 0xF: fluid_synth_system_reset (p_sys->synth); break; } uint8_t p1 = (p_block->i_buffer > 1) ? (p_block->p_buffer[1] & 0x7f) : 0; uint8_t p2 = (p_block->i_buffer > 2) ? (p_block->p_buffer[2] & 0x7f) : 0; switch (event & 0xF0) { case 0x80: fluid_synth_noteoff (p_sys->synth, channel, p1); break; case 0x90: fluid_synth_noteon (p_sys->synth, channel, p1, p2); break; /*case 0xA0: note aftertouch not implemented */ case 0xB0: fluid_synth_cc (p_sys->synth, channel, p1, p2); break; case 0xC0: fluid_synth_program_change (p_sys->synth, channel, p1); break; case 0xD0: fluid_synth_channel_pressure (p_sys->synth, channel, p1); break; case 0xE0: fluid_synth_pitch_bend (p_sys->synth, channel, (p2 << 7) | p1); break; } unsigned samples = (p_block->i_pts - date_Get (&p_sys->end_date)) * 441 / 10000; if (samples == 0) goto drop; p_out = decoder_NewAudioBuffer (p_dec, samples); if (p_out == NULL) goto drop; p_out->i_pts = date_Get (&p_sys->end_date ); p_out->i_length = date_Increment (&p_sys->end_date, samples) - p_out->i_pts; if (!p_sys->fixed) fluid_synth_write_float (p_sys->synth, samples, p_out->p_buffer, 0, 2, p_out->p_buffer, 1, 2); else fluid_synth_write_s16 (p_sys->synth, samples, (int16_t *)p_out->p_buffer, 0, 2, (int16_t *)p_out->p_buffer, 1, 2); drop: block_Release (p_block); return p_out; }