📄 pcm_alsa.c
字号:
/*================================================================== * pcm_alsa.c - ALSA PCM audio support * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include "config.h"/* currently disabled */#if 0#ifdef ALSA_SUPPORT#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <glib.h>#include <gdk/gdk.h>#include <sys/poll.h>#include "alsa.h"#include "pcm.h"#include "pcm_alsa.h"#include "smurfcfg.h"#include "util.h"#include "i18n.h"#include <sys/asoundlib.h>#define PCM_ALSA_NUM_CHUNKS 2#define PCM_ALSA_CHUNK_SIZE 50000static void pcm_alsa_play_callback (void);static gint pcm_alsa_set_params (gint width, gint signd, gint chans, gint rate);gboolean pcm_alsa_active = FALSE;static snd_pcm_t *pcm_alsa_handle;static gint pcm_alsa_card = 0;static gint pcm_alsa_device = 0;static snd_pcm_format_t pcm_format;static gint pcm_channels;static gint bits_per_sample;static gint bytes_per_frame;static gint buffer_size;static gint chunk_size;static gint chunk_bytes;static void *audio_buffer;static gint pcm_fd;static gint pcm_outptag;PCMPlayBackFunc *pcm_play_func;/* get the configuration file values for ALSA PCM */voidpcm_alsa_load_config (void){}#ifdef NEW_ALSA /* New ALSA PCM API */gintpcm_alsa_play (gint width, gboolean signd, gint chans, gint rate, PCMPlayBackFunc *play_func){ struct pollfd pfd; gint err; gchar *s; s = g_strdup_printf ("hw:%d,%d", pcm_alsa_card, pcm_alsa_device); err = snd_pcm_open(&pcm_alsa_handle, s, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); g_free (s); if (err < 0) return (logit (LogFubar, _("Failed to open ALSA audio interface: %s"), snd_strerror (err))); if ((err = snd_pcm_nonblock (pcm_alsa_handle, TRUE)) < 0) { snd_pcm_close (pcm_alsa_handle); return (logit (LogFubar, _("Failed to set ALSA audio to non-blocking: %s"), snd_strerror (err))); } /* set format params */ if (!pcm_alsa_set_params (width, signd, chans, rate)) { snd_pcm_close (pcm_alsa_handle); return (FAIL); } /* allocate audio chunk buffer (fraction of total audio buffer) */ audio_buffer = g_malloc0 (chunk_bytes); /* get the file descriptor for the opened PCM device */ err = snd_pcm_poll_descriptors (pcm_alsa_handle, &pfd, 1); if (err <= 0 || !(pfd.events & POLLOUT)) { snd_pcm_close (pcm_alsa_handle); return (logit (LogFubar, _("Failed to get ALSA PCM file descriptor: %s"), snd_strerror (err))); } pcm_fd = pfd.fd; pcm_play_func = play_func; pcm_outptag = gdk_input_add (pcm_fd, GDK_INPUT_WRITE, (GdkInputFunction)pcm_alsa_play_callback, NULL); pcm_alsa_active = TRUE; return (OK);}static voidpcm_alsa_play_callback (void){ gint count; gint err; if (!pcm_alsa_active) return; count = (*pcm_play_func)(chunk_size, audio_buffer); if (count == -1) { pcm_alsa_stop (); return; } if (count < chunk_size) snd_pcm_format_set_silence (pcm_format, audio_buffer + bytes_per_frame * count, (chunk_size - count) * pcm_channels); err = snd_pcm_writei (pcm_alsa_handle, audio_buffer, chunk_size); if (err == -EPIPE) /* XRUN occured? */ { if ((err = snd_pcm_prepare (pcm_alsa_handle) < 0)) { pcm_alsa_stop (); logit (LogFubar, _("ALSA PCM: Failed to recover from an underrun: %s"), snd_strerror (err)); return; } } else if (err < 0) { pcm_alsa_stop (); logit (LogFubar, _("ALSA PCM write error: %s"), snd_strerror (err)); return; }}voidpcm_alsa_stop (void){ if (!pcm_alsa_active) return; gdk_input_remove (pcm_outptag); snd_pcm_close (pcm_alsa_handle);}static gintpcm_alsa_set_params (gint width, gint signd, gint chans, gint rate){ snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_hw_params_alloca (¶ms); snd_pcm_sw_params_alloca (&swparams); if (snd_pcm_hw_params_any (pcm_alsa_handle, params) < 0) return (logit (LogFubar, _("ALSA PCM: device has no available options"))); if (snd_pcm_hw_params_set_access (pcm_alsa_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) return (logit (LogFubar, _("ALSA PCM: interleaved access not available"))); switch (width) { case 8: if (signd) pcm_format = SND_PCM_FORMAT_S8; else pcm_format = SND_PCM_FORMAT_U8; break; case 16: if (signd) pcm_format = SND_PCM_FORMAT_S16; else pcm_format = SND_PCM_FORMAT_U16; break; default: return (logit (LogFubar, _("Invalid bit width '%d'"), width)); } if (snd_pcm_hw_params_set_format (pcm_alsa_handle, params, pcm_format) < 0) return (logit (LogFubar, _("ALSA PCM: Failed to set sample format"))); if (snd_pcm_hw_params_set_channels (pcm_alsa_handle, params, chans) < 0) return (logit (LogFubar, _("ALSA PCM: Failed to set number of channels"))); if (snd_pcm_hw_params_set_rate_near (pcm_alsa_handle, params, rate, NULL) < 0) return (logit (LogFubar, _("ALSA PCM: Failed to set sampling rate"))); if (snd_pcm_hw_params_set_buffer_time_near (pcm_alsa_handle, params, PCM_ALSA_CHUNK_SIZE * PCM_ALSA_NUM_CHUNKS, NULL) < 0) return (logit (LogFubar, _("ALSA PCM: Failed to set buffer size"))); if (snd_pcm_hw_params_set_period_time_near (pcm_alsa_handle, params, PCM_ALSA_CHUNK_SIZE, NULL) < 0) return (logit (LogFubar, _("ALSA PCM: Failed to set buffer fragment size"))); if (snd_pcm_hw_params (pcm_alsa_handle, params) < 0) return (logit (LogFubar, _("ALSA PCM: Failed to set hardware parameters"))); buffer_size = snd_pcm_hw_params_get_buffer_size (params); chunk_size = snd_pcm_hw_params_get_period_size (params, NULL); snd_pcm_sw_params_current (pcm_alsa_handle, swparams); if (snd_pcm_sw_params_set_xrun_mode (pcm_alsa_handle, swparams, SND_PCM_XRUN_STOP) < 0) return (logit (LogFubar, _("ALSA PCM: Failed to set xrun mode"))); snd_pcm_sw_params (pcm_alsa_handle, swparams); bits_per_sample = snd_pcm_format_physical_width (pcm_format); bytes_per_frame = chans * bits_per_sample / 8; chunk_bytes = chunk_size * bytes_per_frame; pcm_channels = chans; return (OK);}#else /* !NEW_ALSA - Older ALSA 0.5.x API */gintpcm_alsa_play (gint width, gboolean signd, gint chans, gint rate, PCMPlayBackFunc *play_func){ return (OK);}voidpcm_alsa_stop (void){}#endif /* #else !NEW_ALSA */#endif /* #ifdef ALSA_SUPPORT */#endif /* temporarily disabled */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -