📄 fmodaudio.c
字号:
}static void fmod_fini_out (HWVoiceOut *hw){ FMODVoiceOut *fmd = (FMODVoiceOut *) hw; if (fmd->fmod_sample) { FSOUND_Sample_Free (fmd->fmod_sample); fmd->fmod_sample = 0; if (fmd->channel >= 0) { FSOUND_StopSound (fmd->channel); } }}static int fmod_init_out (HWVoiceOut *hw, audsettings_t *as){ int bits16, mode, channel; FMODVoiceOut *fmd = (FMODVoiceOut *) hw; mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0); fmd->fmod_sample = FSOUND_Sample_Alloc ( FSOUND_FREE, /* index */ conf.nb_samples, /* length */ mode, /* mode */ as->freq, /* freq */ 255, /* volume */ 128, /* pan */ 255 /* priority */ ); if (!fmd->fmod_sample) { fmod_logerr2 ("DAC", "Failed to allocate FMOD sample\n"); return -1; } channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1); if (channel < 0) { fmod_logerr2 ("DAC", "Failed to start playing sound\n"); FSOUND_Sample_Free (fmd->fmod_sample); return -1; } fmd->channel = channel; /* FMOD always operates on little endian frames? */ audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0)); bits16 = (mode & FSOUND_16BITS) != 0; hw->samples = conf.nb_samples; return 0;}static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...){ int status; FMODVoiceOut *fmd = (FMODVoiceOut *) hw; switch (cmd) { case VOICE_ENABLE: fmod_clear_sample (fmd); status = FSOUND_SetPaused (fmd->channel, 0); if (!status) { fmod_logerr ("Failed to resume channel %d\n", fmd->channel); } break; case VOICE_DISABLE: status = FSOUND_SetPaused (fmd->channel, 1); if (!status) { fmod_logerr ("Failed to pause channel %d\n", fmd->channel); } break; } return 0;}static int fmod_init_in (HWVoiceIn *hw, audsettings_t *as){ int bits16, mode; FMODVoiceIn *fmd = (FMODVoiceIn *) hw; if (conf.broken_adc) { return -1; } mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0); fmd->fmod_sample = FSOUND_Sample_Alloc ( FSOUND_FREE, /* index */ conf.nb_samples, /* length */ mode, /* mode */ as->freq, /* freq */ 255, /* volume */ 128, /* pan */ 255 /* priority */ ); if (!fmd->fmod_sample) { fmod_logerr2 ("ADC", "Failed to allocate FMOD sample\n"); return -1; } /* FMOD always operates on little endian frames? */ audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0)); bits16 = (mode & FSOUND_16BITS) != 0; hw->samples = conf.nb_samples; return 0;}static void fmod_fini_in (HWVoiceIn *hw){ FMODVoiceIn *fmd = (FMODVoiceIn *) hw; if (fmd->fmod_sample) { FSOUND_Record_Stop (); FSOUND_Sample_Free (fmd->fmod_sample); fmd->fmod_sample = 0; }}static int fmod_run_in (HWVoiceIn *hw){ FMODVoiceIn *fmd = (FMODVoiceIn *) hw; int hwshift = hw->info.shift; int live, dead, new_pos, len; unsigned int blen1 = 0, blen2 = 0; unsigned int len1, len2; unsigned int decr; void *p1, *p2; live = audio_pcm_hw_get_live_in (hw); dead = hw->samples - live; if (!dead) { return 0; } new_pos = FSOUND_Record_GetPosition (); if (new_pos < 0) { fmod_logerr ("Could not get recording position\n"); return 0; } len = audio_ring_dist (new_pos, hw->wpos, hw->samples); if (!len) { return 0; } len = audio_MIN (len, dead); if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info, hw->wpos, len, &p1, &p2, &blen1, &blen2)) { return 0; } len1 = blen1 >> hwshift; len2 = blen2 >> hwshift; decr = len1 + len2; if (p1 && blen1) { hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume); } if (p2 && len2) { hw->conv (hw->conv_buf, p2, len2, &nominal_volume); } fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2); hw->wpos = (hw->wpos + decr) % hw->samples; return decr;}static struct { const char *name; int type;} drvtab[] = { {"none", FSOUND_OUTPUT_NOSOUND},#ifdef _WIN32 {"winmm", FSOUND_OUTPUT_WINMM}, {"dsound", FSOUND_OUTPUT_DSOUND}, {"a3d", FSOUND_OUTPUT_A3D}, {"asio", FSOUND_OUTPUT_ASIO},#endif#ifdef __linux__ {"oss", FSOUND_OUTPUT_OSS}, {"alsa", FSOUND_OUTPUT_ALSA}, {"esd", FSOUND_OUTPUT_ESD},#endif#ifdef __APPLE__ {"mac", FSOUND_OUTPUT_MAC},#endif#if 0 {"xbox", FSOUND_OUTPUT_XBOX}, {"ps2", FSOUND_OUTPUT_PS2}, {"gcube", FSOUND_OUTPUT_GC},#endif {"none-realtime", FSOUND_OUTPUT_NOSOUND_NONREALTIME}};static void *fmod_audio_init (void){ size_t i; double ver; int status; int output_type = -1; const char *drv = conf.drvname; ver = FSOUND_GetVersion (); if (ver < FMOD_VERSION) { dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION); return NULL; }#ifdef __linux__ if (ver < 3.75) { dolog ("FMOD before 3.75 has bug preventing ADC from working\n" "ADC will be disabled.\n"); conf.broken_adc = 1; }#endif if (drv) { int found = 0; for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { if (!strcmp (drv, drvtab[i].name)) { output_type = drvtab[i].type; found = 1; break; } } if (!found) { dolog ("Unknown FMOD driver `%s'\n", drv); dolog ("Valid drivers:\n"); for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) { dolog (" %s\n", drvtab[i].name); } } } if (output_type != -1) { status = FSOUND_SetOutput (output_type); if (!status) { fmod_logerr ("FSOUND_SetOutput(%d) failed\n", output_type); return NULL; } } if (conf.bufsize) { status = FSOUND_SetBufferSize (conf.bufsize); if (!status) { fmod_logerr ("FSOUND_SetBufferSize (%d) failed\n", conf.bufsize); } } status = FSOUND_Init (conf.freq, conf.nb_channels, 0); if (!status) { fmod_logerr ("FSOUND_Init failed\n"); return NULL; } return &conf;}static int fmod_read (SWVoiceIn *sw, void *buf, int size){ return audio_pcm_sw_read (sw, buf, size);}static int fmod_ctl_in (HWVoiceIn *hw, int cmd, ...){ int status; FMODVoiceIn *fmd = (FMODVoiceIn *) hw; switch (cmd) { case VOICE_ENABLE: status = FSOUND_Record_StartSample (fmd->fmod_sample, 1); if (!status) { fmod_logerr ("Failed to start recording\n"); } break; case VOICE_DISABLE: status = FSOUND_Record_Stop (); if (!status) { fmod_logerr ("Failed to stop recording\n"); } break; } return 0;}static void fmod_audio_fini (void *opaque){ (void) opaque; FSOUND_Close ();}static struct audio_option fmod_options[] = { {"DRV", AUD_OPT_STR, &conf.drvname, "FMOD driver", NULL, 0}, {"FREQ", AUD_OPT_INT, &conf.freq, "Default frequency", NULL, 0}, {"SAMPLES", AUD_OPT_INT, &conf.nb_samples, "Buffer size in samples", NULL, 0}, {"CHANNELS", AUD_OPT_INT, &conf.nb_channels, "Number of default channels (1 - mono, 2 - stereo)", NULL, 0}, {"BUFSIZE", AUD_OPT_INT, &conf.bufsize, "(undocumented)", NULL, 0},#if 0 {"THRESHOLD", AUD_OPT_INT, &conf.threshold, "(undocumented)"},#endif {NULL, 0, NULL, NULL, NULL, 0}};static struct audio_pcm_ops fmod_pcm_ops = { fmod_init_out, fmod_fini_out, fmod_run_out, fmod_write, fmod_ctl_out, fmod_init_in, fmod_fini_in, fmod_run_in, fmod_read, fmod_ctl_in};struct audio_driver fmod_audio_driver = { INIT_FIELD (name = ) "fmod", INIT_FIELD (descr = ) "FMOD 3.xx http://www.fmod.org", INIT_FIELD (options = ) fmod_options, INIT_FIELD (init = ) fmod_audio_init, INIT_FIELD (fini = ) fmod_audio_fini, INIT_FIELD (pcm_ops = ) &fmod_pcm_ops, INIT_FIELD (can_be_default = ) 1, INIT_FIELD (max_voices_out = ) INT_MAX, INIT_FIELD (max_voices_in = ) INT_MAX, INIT_FIELD (voice_size_out = ) sizeof (FMODVoiceOut), INIT_FIELD (voice_size_in = ) sizeof (FMODVoiceIn)};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -