void SoundPlayer::main() { BH_TRACE_INIT("SoundPlayer"); unsigned i; for(i = 0; i < retries; ++i) { if(snd_pcm_open(&handle, "hw:0", SND_PCM_STREAM_PLAYBACK, 0) >= 0) break; Thread::sleep(retryDelay); } ASSERT(i < retries); snd_pcm_hw_params_t* params; VERIFY(!snd_pcm_hw_params_malloc(¶ms)); VERIFY(!snd_pcm_hw_params_any(handle, params)); VERIFY(!snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)); VERIFY(!snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)); VERIFY(!snd_pcm_hw_params_set_rate_near(handle, params, &sampleRate, 0));; VERIFY(!snd_pcm_hw_params_set_channels(handle, params, 2)); VERIFY(!snd_pcm_hw_params(handle, params)); VERIFY(!snd_pcm_hw_params_get_period_size(params, &periodSize, 0)); snd_pcm_hw_params_free(params); while(isRunning() && !closing) { flush(); VERIFY(sem.wait()); } VERIFY(!snd_pcm_close(handle)); }
static void alsa_log(snd_pcm_hw_params_t* hw_params, snd_pcm_sw_params_t* sw_params) { unsigned period_time; snd_pcm_uframes_t period_size; unsigned period_count; unsigned buffer_time; snd_pcm_uframes_t buffer_size; unsigned tick_time; snd_pcm_uframes_t xfer_align; snd_pcm_hw_params_get_period_time(hw_params, &period_time, 0); snd_pcm_hw_params_get_period_size(hw_params, &period_size, 0); snd_pcm_hw_params_get_periods(hw_params, &period_count, 0); snd_pcm_hw_params_get_buffer_time(hw_params, &buffer_time, 0); snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size); snd_pcm_hw_params_get_tick_time(hw_params, &tick_time, 0); log_std(("sound:alsa: hw period_time %g [us], period_size %d, periods %d, buffer_time %g [us], buffer_size %d, tick_time %g [us]\n", (double)(period_time / 1000000.0), (unsigned)period_size, (unsigned)period_count, (double)(buffer_time / 1000000.0), (unsigned)buffer_size, (double)(tick_time / 1000000.0) )); snd_pcm_sw_params_get_xfer_align(sw_params, &xfer_align); log_std(("sound:alsa: sw xfer_align %d\n", (unsigned)xfer_align )); }
void audio_init(void) { int ret, dir; unsigned int rate; snd_pcm_hw_params_t * params; rate = 44100; frames = 32; ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (ret < 0) { fprintf(stderr, "Unable to open pcm device: %s\n", snd_strerror(ret)); exit(EXIT_FAILURE); } snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(handle, params, 2); snd_pcm_hw_params_set_rate_near(handle, params, &rate, &dir); snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); ret = snd_pcm_hw_params(handle, params); if (ret < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(ret)); exit(EXIT_FAILURE); } snd_pcm_hw_params_get_period_size(params, &frames, &dir); }
/************************************************************************** * wodPlayer_NotifyCompletions [internal] * * Notifies and remove from queue all wavehdrs which have been played to * the speaker (ie. they have cleared the ALSA buffer). If force is true, * we notify all wavehdrs and remove them all from the queue even if they * are unplayed or part of a loop. */ static DWORD wodPlayer_NotifyCompletions(WINE_WAVEDEV* wwo, BOOL force) { LPWAVEHDR lpWaveHdr; /* Start from lpQueuePtr and keep notifying until: * - we hit an unwritten wavehdr * - we hit the beginning of a running loop * - we hit a wavehdr which hasn't finished playing */ for (;;) { lpWaveHdr = wwo->lpQueuePtr; if (!lpWaveHdr) {TRACE("Empty queue\n"); break;} if (!force) { snd_pcm_uframes_t frames; snd_pcm_hw_params_get_period_size(wwo->hw_params, &frames, NULL); if (lpWaveHdr == wwo->lpPlayPtr) {TRACE("play %p\n", lpWaveHdr); break;} if (lpWaveHdr == wwo->lpLoopPtr) {TRACE("loop %p\n", lpWaveHdr); break;} if (lpWaveHdr->reserved > wwo->dwPlayedTotal + frames) {TRACE("still playing %p (%lu/%u)\n", lpWaveHdr, lpWaveHdr->reserved, wwo->dwPlayedTotal);break;} } wwo->dwPlayedTotal += lpWaveHdr->reserved - wwo->dwPlayedTotal; wwo->lpQueuePtr = lpWaveHdr->lpNext; lpWaveHdr->dwFlags &= ~WHDR_INQUEUE; lpWaveHdr->dwFlags |= WHDR_DONE; wodNotifyClient(wwo, WOM_DONE, (DWORD_PTR)lpWaveHdr, 0); } return (lpWaveHdr && lpWaveHdr != wwo->lpPlayPtr && lpWaveHdr != wwo->lpLoopPtr) ? wodPlayer_NotifyWait(wwo, lpWaveHdr) : INFINITE; }
void initsound(int samplerate, int channels) { int dir, pcmrc; /* Open the PCM device in playback mode */ snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); /* Allocate parameters object and fill it with default values*/ snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(pcm_handle, params); /* Set parameters */ snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(pcm_handle, params, channels); snd_pcm_hw_params_set_rate(pcm_handle, params, samplerate, 0); /* Write parameters */ snd_pcm_hw_params(pcm_handle, params); /* Allocate buffer to hold single period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); buf = malloc(frames * channels * 2 * BUFFER_NUM); }
/** * This method will determine, based upon the size of each frame and the number of frames between interrupts the required size of the buffer that is to store the data. * @return */ int AudioInterface::getRequiredBufferSize() { int dir; int size; snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * this->channels * 2; /* 2 bytes/sample */ std::cout << "Get re: " << channels << ":" << frames << std::endl; return size; }
bool SoundProcessor::SetUpRecorder(){ rc_m = snd_pcm_open(&handle_m, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc_m < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc_m)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms_m); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle_m, params_m); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle_m, params_m, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle_m, params_m, SND_PCM_FORMAT_U8); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle_m, params_m, 1); /* 44100 bits/second sampling rate (CD quality) */ val_m = 8000; snd_pcm_hw_params_set_rate_near(handle_m, params_m, &val_m, &dir_m); /* Set period size to 32 frames. */ //frames = 32; snd_pcm_hw_params_set_period_size_near(handle_m, params_m, &frames, &dir_m); /* Write the parameters to the driver */ rc_m = snd_pcm_hw_params(handle_m, params_m); if (rc_m < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc_m)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params_m, &frames, &dir_m); size = frames; /* 2 bytes/sample, 2 channels */ buffer_m = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params_m, &val_m, &dir_m); return true; }
void Recorder::initRecoder() { int rc; snd_pcm_hw_params_t *params; unsigned int val; int dir=0; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default",SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, CHANNELS); /* 44100 bits/second sampling rate (CD quality) */ val = SAMPLERATE; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr,"unable to set hw parameters: %s\n",snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params,&frames, &dir); size = frames * 2; /* 2 bytes/sample, 2 channels */ /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params,&val, &dir); //loops = 5000000 / val; //获取5秒中所对应的loop这里用不到 }
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access) { int err, dir; /* choose all parameters */ err = snd_pcm_hw_params_any(handle,params); if (err < 0) { printf("Access type not available for playback: %s\n", snd_strerror(err)); return err; } /* set the sample format */ err = snd_pcm_hw_params_set_format(handle, params, alsa_format); if (err < 0) { printf("Sample format not available for playback: %s\n", snd_strerror(err)); return err; } /* set the count of channels */ err = snd_pcm_hw_params_set_channels(handle, params, channels); if (err < 0) { printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err)); return err; } /* set the stream rate */ err = snd_pcm_hw_params_set_rate_near(handle, params, rate, 0); if (err < 0) { printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); return err; } if (err != rate) { printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err); return -EINVAL; } /* set buffer time */ err = snd_pcm_hw_params_set_buffer_time_near(handle, params, buffer_time, &dir); if (err < 0) { printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err)); return err; } buffer_size = snd_pcm_hw_params_get_buffer_size(params); /* set period time */ err = snd_pcm_hw_params_set_period_time_near(handle, params, period_time, &dir); if (err < 0) { printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err)); return err; } period_size = snd_pcm_hw_params_get_period_size(params, &dir); /* write the parameters to device */ err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to set hw params for playback: %s\n", snd_strerror(err)); return err; } return 0; }
int audio_capture_init(char *audio_dev) { unsigned int val; int dir, rc, size; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); return -1; } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(&hw_params); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, hw_params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE); /* 1 channel mono */ snd_pcm_hw_params_set_channels(handle, hw_params, 1); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, hw_params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, hw_params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, hw_params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); return -1; } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ frame_buffer = (char *) malloc(size); printf("- Allocated %d bytes frame buffer\n", size); snd_pcm_hw_params_get_period_time(hw_params, &val, &dir); return 0; }
static void set_params(void) { hwparams.format=SND_PCM_FORMAT_S16_LE; hwparams.channels=2; hwparams.rate=44100; snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_format(handle, params, hwparams.format); snd_pcm_hw_params_set_channels(handle, params, hwparams.channels); snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0); buffer_time=0; snd_pcm_hw_params_get_buffer_time_max(params,&buffer_time, 0); period_time=125000; snd_pcm_hw_params_set_period_time_near(handle, params,&period_time, 0); buffer_time = 500000; snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0); /*monotonic = */snd_pcm_hw_params_is_monotonic(params); /*can_pause = */snd_pcm_hw_params_can_pause(params); printf("sizeof(params) : %d\n",sizeof(params)); snd_pcm_hw_params(handle, params); snd_pcm_uframes_t buffer_size; snd_pcm_hw_params_get_period_size(params, &chunk_size, 0); size_t n=chunk_size; snd_pcm_sw_params_set_avail_min(handle, swparams, n); snd_pcm_uframes_t start_threshold, stop_threshold; start_threshold=22050; snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); stop_threshold=22050; snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); snd_pcm_format_physical_width(hwparams.format); }
/**************************************************************************************** * 函数名: init_alsa_play * 输 入: 无 * 输 出: 无 * 功能说明:alsa音频播放器初始化 * * ******************************************************************************************/ void init_alsa_play() { snd_pcm_hw_params_t *params; unsigned int val; int dir; /* Open PCM device for playback. */ rc=snd_pcm_open(&handle,"plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0); if (rc< 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle,params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format 格式*/ snd_pcm_hw_params_set_format(handle,params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) 声道*/ snd_pcm_hw_params_set_channels(handle, params, channels); /* 32000 bits/second sampling rate (CD quality) 采样率设置*/ snd_pcm_hw_params_set_rate_near(handle,params, &rate, &dir); /* Set period size to 32 frames. */ frames = SAMPLERATE/1000*READMSFORONCE; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /*Use a buffer large enough to hold one period*/ snd_pcm_hw_params_get_period_size(params, &frames, &dir); //32个采样点算一帧 size = frames * (channels); /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); }
void carmen_sound_set_device_parameters(snd_pcm_t *handle, int sampling_rate, int num_frames) { int rc, dir; unsigned int val; snd_pcm_hw_params_t *params; snd_pcm_uframes_t frames; val = sampling_rate; frames = (snd_pcm_uframes_t) num_frames; /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* set bits/second sampling rate */ snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to num of frames. */ snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) exit(printf("unable to set hw parameters: %s\n", snd_strerror(rc))); /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); // @TODO: pesquisar por que tem que ler um pouco que vem vazio nao sei por que... char buffer[4 * 32]; rc = snd_pcm_readi(handle, buffer, 32); }
void AudioWalkera::setupAlsa(){ int dir; int t = 0, i, c; rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if(rc < 0) exitError("Could not open pcm device"); snd_pcm_hw_params_alloca(¶ms); //rc = setupHardware(handle, params, &dir); snd_pcm_uframes_t frames_inner; unsigned int val; snd_pcm_hw_params_any(handle, params); snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels(handle, params, 1); val = 48000; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); frames_inner = 2304; snd_pcm_hw_params_set_period_size_near(handle, params, &frames_inner, &dir); rc = snd_pcm_hw_params(handle, params); if(rc < 0) exitError("Could not set hardware parameters"); snd_pcm_hw_params_get_period_size(params, &frames, &dir); buffer = (short*) calloc(frames, sizeof(short)); }
static int alsa_set_hwparams() { snd_pcm_hw_params_t *hwp; snd_pcm_sw_params_t *swp; int dir = 1; unsigned period_time; snd_pcm_uframes_t buffer_size, period_size; snd_pcm_hw_params_alloca(&hwp); snd_pcm_sw_params_alloca(&swp); // ALSA bug? If we request 44100 Hz, it rounds the value up to 48000... alsa_hw.rate--; if (alsa_error("hw_params_any", snd_pcm_hw_params_any(alsa_hw.handle, hwp)) || alsa_error("hw_params_set_format", snd_pcm_hw_params_set_format(alsa_hw.handle, hwp, alsa_hw.format)) || alsa_error("hw_params_set_channels", snd_pcm_hw_params_set_channels(alsa_hw.handle, hwp, alsa_hw.num_channels)) || alsa_error("hw_params_set_rate_near", snd_pcm_hw_params_set_rate_near(alsa_hw.handle, hwp, &alsa_hw.rate, &dir)) || alsa_error("hw_params_set_access", snd_pcm_hw_params_set_access(alsa_hw.handle, hwp, SND_PCM_ACCESS_RW_INTERLEAVED)) || alsa_error("hw_params_set_buffer_time_near", snd_pcm_hw_params_set_buffer_time_near(alsa_hw.handle, hwp, &alsa_hw.buffer_time, 0))) return -1; /* How often to call our SIGIO handler (~40Hz) */ period_time = alsa_hw.buffer_time / 4; if (alsa_error ("hw_params_set_period_time_near", snd_pcm_hw_params_set_period_time_near(alsa_hw.handle, hwp, &period_time, &dir)) || alsa_error("hw_params_get_buffer_size", snd_pcm_hw_params_get_buffer_size(hwp, &buffer_size)) || alsa_error("hw_params_get_period_size", snd_pcm_hw_params_get_period_size(hwp, &period_size, 0)) || alsa_error("hw_params", snd_pcm_hw_params(alsa_hw.handle, hwp))) return -1; snd_pcm_sw_params_current(alsa_hw.handle, swp); if (alsa_error ("sw_params_set_start_threshold", snd_pcm_sw_params_set_start_threshold(alsa_hw.handle, swp, period_size)) || alsa_error("sw_params_set_avail_min", snd_pcm_sw_params_set_avail_min(alsa_hw.handle, swp, period_size)) || alsa_error("sw_params", snd_pcm_sw_params(alsa_hw.handle, swp))) return -1; return 0; }
int sound_init () { int rc; rc = snd_pcm_open (&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { fprintf (stderr, "unable to open pcm device: %s\n", snd_strerror (rc)); return rc; } g_paused = 0; snd_pcm_hw_params_alloca (¶ms); snd_pcm_hw_params_any (handle, params); snd_pcm_hw_params_set_access (handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format (handle, params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels (handle, params, CHANNELS); val = RATE; snd_pcm_hw_params_set_rate_near (handle, params, &val, &dir); frames = FRAMES; snd_pcm_hw_params_set_period_size_near (handle, params, &frames, &dir); rc = snd_pcm_hw_params (handle, params); if (rc < 0) return rc; snd_pcm_hw_params_get_period_size (params, &frames, &dir); snd_pcm_hw_params_get_period_time (params, &val, &dir); return 0; }
SoundOutput_alsa::SoundOutput_alsa(int mixing_frequency, int mixing_latency) : SoundOutput_Impl(mixing_frequency, mixing_latency), frames_in_buffer(4096), frames_in_period(1024) { int rc; snd_pcm_hw_params_t *hwparams; rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0) { log_event("warn", "ClanSound: Couldn't open sound device, disabling sound"); handle = nullptr; return; } snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_any(handle, hwparams); snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_FLOAT); snd_pcm_hw_params_set_channels(handle, hwparams, 2); snd_pcm_hw_params_set_rate_near(handle, hwparams, (unsigned int *)&this->mixing_frequency, nullptr); snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &frames_in_buffer); frames_in_period = frames_in_buffer / 4; snd_pcm_hw_params_set_period_size_near(handle, hwparams, &frames_in_period, nullptr); rc = snd_pcm_hw_params(handle, hwparams); if (rc < 0) { log_event("warn", "ClanSound: Couldn't initialize sound device, disabling sound"); snd_pcm_close(handle); handle = nullptr; return; } snd_pcm_hw_params_get_period_size(hwparams, &frames_in_period, nullptr); start_mixer_thread(); }
// 声卡采集初始化 struct SoundInfo* sound_info_record_new() { struct SoundInfo *info = (struct SoundInfo*)malloc(sizeof(struct SoundInfo)); int rc; int dir = 0; info->channels = 2; info->frequency = 44100; rc = snd_pcm_open(&info->handle, "default", SND_PCM_STREAM_CAPTURE, 0); snd_pcm_hw_params_alloca(&info->params); rc = snd_pcm_hw_params_any(info->handle, info->params); rc = snd_pcm_hw_params_set_access(info->handle, info->params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(info->handle, info->params, SND_PCM_FORMAT_S16_LE); rc = snd_pcm_hw_params_set_channels(info->handle, info->params, info->channels); unsigned int val = info->frequency; rc = snd_pcm_hw_params_set_rate_near(info->handle, info->params, &val, &dir); rc = snd_pcm_hw_params(info->handle, info->params); info->frames = 32;//"frames"=channel*size/8=4, frames = "frames"*8 one period contains 8 "frames" snd_pcm_hw_params_set_period_size_near(info->handle, info->params, &info->frames, &dir); rc = snd_pcm_hw_params(info->handle, info->params); snd_pcm_hw_params_get_period_size(info->params, &info->frames, &dir); info->bufferSize = info->frames * 4; info->buffer = (char*) malloc(info->bufferSize); snd_pcm_hw_params_get_period_time(info->params, &val, &dir); memset(info->buffer, 0, info->bufferSize); return info; }
int setparams_set(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_sw_params_t *swparams, const char *id) { int err; snd_pcm_uframes_t val; err = snd_pcm_hw_params(handle, params); if (err < 0) { printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err)); return err; } err = snd_pcm_sw_params_current(handle, swparams); if (err < 0) { printf("Unable to determine current swparams for %s: %s\n", id, snd_strerror(err)); return err; } err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff); if (err < 0) { printf("Unable to set start threshold mode for %s: %s\n", id, snd_strerror(err)); return err; } if (!block) val = 4; else snd_pcm_hw_params_get_period_size(params, &val, NULL); err = snd_pcm_sw_params_set_avail_min(handle, swparams, val); if (err < 0) { printf("Unable to set avail min for %s: %s\n", id, snd_strerror(err)); return err; } err = snd_pcm_sw_params(handle, swparams); if (err < 0) { printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err)); return err; } return 0; }
int snd_send(FILE * fp, size_t n) { snd_pcm_format_t format; unsigned int nchannels; snd_pcm_uframes_t period; snd_pcm_hw_params_t *params; snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_current(pcm, params); snd_pcm_hw_params_get_format(params, &format); snd_pcm_hw_params_get_channels(params, &nchannels); snd_pcm_hw_params_get_period_size(params, &period, 0); int framesize = snd_pcm_format_width(format) / 8 * nchannels; unsigned char buf[period * framesize * 128]; size_t l; while (n > sizeof(buf)) { if ((l = fread(buf, 1, sizeof(buf), fp))) { switch (snd_pcm_writei(pcm, buf, l / framesize)) { case -EBADF: return -1; case -EPIPE: #ifndef NDEBUG snd_pcm_recover(pcm, -EPIPE, 0); #else snd_pcm_prepare(pcm); #endif } } else goto EOS; n -= l; } if ((l = fread(buf, 1, n, fp))) snd_pcm_writei(pcm, buf, l / framesize); if (l < n) EOS:if (ftell(fp) > 0) eputs("Unexpected end of stream"); return snd_pcm_drain(pcm); }
void alsa_print_info(snd_pcm_t * handle, snd_pcm_hw_params_t * hwp) { printf("device [%s] opened with\n", snd_pcm_name(handle)); printf("\tstate=%s\n", snd_pcm_state_name(snd_pcm_state(handle))); unsigned int val, val2; snd_pcm_hw_params_get_access(hwp, (snd_pcm_access_t *) &val); printf("\taccess_type=%s\n", snd_pcm_access_name((snd_pcm_access_t)val)); snd_pcm_hw_params_get_format(hwp, (snd_pcm_format_t *) &val); printf("\tformat=%s\n", snd_pcm_format_name((snd_pcm_format_t) val) ); snd_pcm_hw_params_get_channels(hwp, &val); printf("\tchannels=%d\n", val); snd_pcm_hw_params_get_rate(hwp, &val, (int *) &val2); printf("\trate=%d fps\n", val); snd_pcm_hw_params_get_period_time(hwp, &val, (int *) &val2); printf("\tperiod_time=%d us\n", val); snd_pcm_uframes_t frames; snd_pcm_hw_params_get_period_size(hwp, &frames, (int *) &val2); printf("\tperiod_size=%d frames\n", (int)frames); snd_pcm_hw_params_get_buffer_size(hwp, (snd_pcm_uframes_t *) &val); printf("\tbuffer_size=%d frames\n", val); snd_pcm_hw_params_get_periods(hwp, &val, (int *) &val2); printf("\tperiods_per_buffer=%d periods\n", val); }
void sound_dev_prepare(const char *device, struct sound_device_t *dev, unsigned int sample_rate, unsigned int channels){ int rc; rc = snd_pcm_open(&(*dev).handle, device, SND_PCM_STREAM_PLAYBACK, 0); if (rc < 0){ exception(snd_strerror(rc),BAD_PCM_DEV); } snd_pcm_hw_params_alloca(&(*dev).params); snd_pcm_hw_params_any((*dev).handle, (*dev).params); snd_pcm_hw_params_set_access((*dev).handle, (*dev).params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format((*dev).handle, (*dev).params, SND_PCM_FORMAT_S16_LE); snd_pcm_hw_params_set_channels((*dev).handle, (*dev).params, channels); snd_pcm_hw_params_set_rate_near((*dev).handle, (*dev).params, &sample_rate, &(*dev).dir); rc = snd_pcm_hw_params((*dev).handle, (*dev).params); if (rc < 0){ exception(snd_strerror(rc), BAD_HW_PARAMS); } snd_pcm_hw_params_get_period_size((*dev).params, &(*dev).frames, &(*dev).dir); (*dev).size = (*dev).frames * 4; snd_pcm_hw_params_get_period_time((*dev).params, &(*dev).val, &(*dev).dir); (*dev).loops = TIME / (*dev).val; (*dev).buff_size_bytes = (*dev).size * (*dev).loops; (*dev).buff_size_frames = (*dev).frames * (*dev).loops; }
int set_pcm_play(FILE *fp) { int rc; int ret; int size; snd_pcm_t* handle; //PCI设备句柄 snd_pcm_hw_params_t* params;//硬件信息和PCM流配置 unsigned int val; int dir=0; snd_pcm_uframes_t frames; char *buffer; int channels=wav_header.wChannels; int frequency=wav_header.nSamplesPersec; int bit=wav_header.wBitsPerSample; int datablock=wav_header.wBlockAlign; unsigned char ch[100]; //用来存储wav文件的头信息 rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if(rc<0) { perror("\nopen PCM device failed:"); exit(1); } snd_pcm_hw_params_alloca(¶ms); //分配params结构体 if(rc<0) { perror("\nsnd_pcm_hw_params_alloca:"); exit(1); } rc=snd_pcm_hw_params_any(handle, params);//初始化params if(rc<0) { perror("\nsnd_pcm_hw_params_any:"); exit(1); } rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //初始化访问权限 if(rc<0) { perror("\nsed_pcm_hw_set_access:"); exit(1); } //采样位数 switch(bit/8) { case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8); break ; case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); break ; case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE); break ; } rc=snd_pcm_hw_params_set_channels(handle, params, channels); //设置声道,1表示单声>道,2表示立体声 if(rc<0) { perror("\nsnd_pcm_hw_params_set_channels:"); exit(1); } val = frequency; rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //设置>频率 if(rc<0) { perror("\nsnd_pcm_hw_params_set_rate_near:"); exit(1); } rc = snd_pcm_hw_params(handle, params); if(rc<0) { perror("\nsnd_pcm_hw_params: "); exit(1); } rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir); /*获取周期长度*/ if(rc<0) { perror("\nsnd_pcm_hw_params_get_period_size:"); exit(1); } size = frames * datablock; /*4 代表数据快长度*/ buffer =(char*)malloc(size); fseek(fp,58,SEEK_SET); //定位歌曲到数据区 while (1) { memset(buffer,0,sizeof(buffer)); ret = fread(buffer, 1, size, fp); if(ret == 0) { printf("歌曲写入结束\n"); break; } else if (ret != size) { } // 写音频数据到PCM设备 while(ret = snd_pcm_writei(handle, buffer, frames)<0) { usleep(2000); if (ret == -EPIPE) { /* EPIPE means underrun */ fprintf(stderr, "underrun occurred\n"); //完成硬件参数设置,使设备准备好 snd_pcm_prepare(handle); } else if (ret < 0) { fprintf(stderr, "error from writei: %s\n", snd_strerror(ret)); } } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }
int ai_alsa_setup(audio_in_t *ai) { snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t buffer_size, period_size; int err; int dir; unsigned int rate; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(ai->alsa.handle, params); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Broken configuration for this PCM: no configurations available.\n"); return -1; } err = snd_pcm_hw_params_set_access(ai->alsa.handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Access type not available.\n"); return -1; } err = snd_pcm_hw_params_set_format(ai->alsa.handle, params, SND_PCM_FORMAT_S16_LE); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Sample format not available.\n"); return -1; } err = snd_pcm_hw_params_set_channels(ai->alsa.handle, params, ai->req_channels); if (err < 0) { snd_pcm_hw_params_get_channels(params, &ai->channels); mp_tmsg(MSGT_TV, MSGL_ERR, "Channel count not available - reverting to default: %d\n", ai->channels); } else { ai->channels = ai->req_channels; } dir = 0; rate = ai->req_samplerate; err = snd_pcm_hw_params_set_rate_near(ai->alsa.handle, params, &rate, &dir); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set samplerate.\n"); } ai->samplerate = rate; dir = 0; ai->alsa.buffer_time = 1000000; err = snd_pcm_hw_params_set_buffer_time_near(ai->alsa.handle, params, &ai->alsa.buffer_time, &dir); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set buffer time.\n"); } dir = 0; ai->alsa.period_time = ai->alsa.buffer_time / 4; err = snd_pcm_hw_params_set_period_time_near(ai->alsa.handle, params, &ai->alsa.period_time, &dir); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Cannot set period time.\n"); } err = snd_pcm_hw_params(ai->alsa.handle, params); if (err < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to install hardware parameters: %s", snd_strerror(err)); snd_pcm_hw_params_dump(params, ai->alsa.log); return -1; } dir = -1; snd_pcm_hw_params_get_period_size(params, &period_size, &dir); snd_pcm_hw_params_get_buffer_size(params, &buffer_size); ai->alsa.chunk_size = period_size; if (period_size == buffer_size) { mp_tmsg(MSGT_TV, MSGL_ERR, "Can't use period equal to buffer size (%u == %lu)\n", ai->alsa.chunk_size, (long)buffer_size); return -1; } snd_pcm_sw_params_current(ai->alsa.handle, swparams); err = snd_pcm_sw_params_set_avail_min(ai->alsa.handle, swparams, ai->alsa.chunk_size); err = snd_pcm_sw_params_set_start_threshold(ai->alsa.handle, swparams, 0); err = snd_pcm_sw_params_set_stop_threshold(ai->alsa.handle, swparams, buffer_size); if (snd_pcm_sw_params(ai->alsa.handle, swparams) < 0) { mp_tmsg(MSGT_TV, MSGL_ERR, "Unable to install software parameters:\n"); snd_pcm_sw_params_dump(swparams, ai->alsa.log); return -1; } if (mp_msg_test(MSGT_TV, MSGL_V)) { snd_pcm_dump(ai->alsa.handle, ai->alsa.log); } ai->alsa.bits_per_sample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE); ai->alsa.bits_per_frame = ai->alsa.bits_per_sample * ai->channels; ai->blocksize = ai->alsa.chunk_size * ai->alsa.bits_per_frame / 8; ai->samplesize = ai->alsa.bits_per_sample; ai->bytes_per_sample = ai->alsa.bits_per_sample/8; return 0; }
static snd_pcm_t * bg_alsa_open(const char * card, gavl_audio_format_t * format, snd_pcm_stream_t stream, gavl_time_t buffer_time, int * convert_4_3) { unsigned int i_tmp; int dir, err; snd_pcm_hw_params_t *hw_params = NULL; // snd_pcm_sw_params_t *sw_params = NULL; snd_pcm_t *ret = NULL; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t period_size; snd_pcm_uframes_t period_size_min = 0; snd_pcm_uframes_t period_size_max = 0; snd_pcm_uframes_t buffer_size_min = 0; snd_pcm_uframes_t buffer_size_max = 0; /* We open in non blocking mode so our process won't hang if the card is busy */ if((err = snd_pcm_open(&ret, card, stream, // SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_CAPTURE SND_PCM_NONBLOCK // SND_PCM_ASYNC ) < 0)) { ret = NULL; bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_open failed for device %s (%s)", card, snd_strerror(err)); goto fail; } /* Now, set blocking mode */ snd_pcm_nonblock(ret, 0); if(snd_pcm_hw_params_malloc(&hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_malloc failed"); goto fail; } if(snd_pcm_hw_params_any(ret, hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_any failed"); goto fail; } /* Interleave mode */ if(snd_pcm_hw_params_set_access(ret, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_access failed"); goto fail; } else format->interleave_mode = GAVL_INTERLEAVE_ALL; /* Sample format */ switch(format->sample_format) { case GAVL_SAMPLE_S8: case GAVL_SAMPLE_U8: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S8) < 0) // if(1) { /* Soundcard support no 8-bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else format->sample_format = GAVL_SAMPLE_S8; break; case GAVL_SAMPLE_S16: case GAVL_SAMPLE_U16: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; break; case GAVL_SAMPLE_S32: #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0) #endif { /* Soundcard supports no 32-bit, try 24 (more probably supported but needs conversion) */ #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0) #endif { /* No 24 bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else { format->sample_format = GAVL_SAMPLE_S32; if(convert_4_3) *convert_4_3 = 1; } } else format->sample_format = GAVL_SAMPLE_S32; break; case GAVL_SAMPLE_FLOAT: case GAVL_SAMPLE_DOUBLE: if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_FLOAT) < 0) { #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S32_BE) < 0) #endif { /* Soundcard supports no 32-bit, try 24 (more probably supported but needs conversion) */ #ifndef WORDS_BIGENDIAN if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3LE) < 0) #else if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S24_3BE) < 0) #endif { /* No 24 bit, try 16 */ if(snd_pcm_hw_params_set_format(ret, hw_params, SND_PCM_FORMAT_S16) < 0) { /* Hopeless */ bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_format failed"); goto fail; } else format->sample_format = GAVL_SAMPLE_S16; } else { format->sample_format = GAVL_SAMPLE_S32; if(convert_4_3) *convert_4_3 = 1; } } else format->sample_format = GAVL_SAMPLE_S32; } else format->sample_format = GAVL_SAMPLE_FLOAT; break; case GAVL_SAMPLE_NONE: goto fail; break; } /* Channels */ if(snd_pcm_hw_params_set_channels(ret, hw_params, format->num_channels) < 0) { if(format->num_channels == 1) /* Mono doesn't work, try stereo */ { if(snd_pcm_hw_params_set_channels(ret, hw_params, 2) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_channels failed (Format has %d channels)", format->num_channels); goto fail; } else { format->num_channels = 2; format->channel_locations[0] = GAVL_CHID_FRONT_LEFT; format->channel_locations[1] = GAVL_CHID_FRONT_RIGHT; } } else { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_channels failed (Format has %d channels)", format->num_channels); goto fail; } } /* Switch off driver side resampling */ #if SND_LIB_VERSION >= 0x010009 snd_pcm_hw_params_set_rate_resample(ret, hw_params, 0); #endif /* Samplerate */ i_tmp = format->samplerate; if(snd_pcm_hw_params_set_rate_near(ret, hw_params, &i_tmp, 0) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_rate_near failed"); goto fail; } if(format->samplerate != i_tmp) { bg_log(BG_LOG_INFO, LOG_DOMAIN, "Samplerate %d not supported by device %s, using %d", format->samplerate, card, i_tmp); } format->samplerate = i_tmp; dir = 0; /* Buffer size */ snd_pcm_hw_params_get_buffer_size_min(hw_params, &buffer_size_min); snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size_max); dir=0; snd_pcm_hw_params_get_period_size_min(hw_params, &period_size_min,&dir); dir=0; snd_pcm_hw_params_get_period_size_max(hw_params, &period_size_max,&dir); buffer_size = gavl_time_to_samples(format->samplerate, buffer_time); if(buffer_size > buffer_size_max) buffer_size = buffer_size_max; if(buffer_size < buffer_size_min) buffer_size = buffer_size_min; period_size = buffer_size / 8; buffer_size = period_size * 8; dir = 0; if(snd_pcm_hw_params_set_period_size_near(ret, hw_params, &period_size, &dir) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_period_size failed"); goto fail; } dir = 0; snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir); dir = 0; if(snd_pcm_hw_params_set_buffer_size_near(ret, hw_params, &buffer_size) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params_set_buffer_size failed"); goto fail; } snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size); format->samples_per_frame = period_size; /* Write params to card */ if(snd_pcm_hw_params (ret, hw_params) < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "snd_pcm_hw_params failed"); goto fail; } snd_pcm_hw_params_free(hw_params); gavl_set_channel_setup(format); // gavl_audio_format_dump(format); return ret; fail: bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Alsa initialization failed"); if(ret) snd_pcm_close(ret); if(hw_params) snd_pcm_hw_params_free(hw_params); return NULL; }
static int Open (vlc_object_t *obj) { demux_t *demux = (demux_t *)obj; demux_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys)); if (unlikely(sys == NULL)) return VLC_ENOMEM; /* Open the device */ const char *device = demux->psz_location; if (device == NULL || !device[0]) device = "default"; const int mode = SND_PCM_NONBLOCK /*| SND_PCM_NO_AUTO_RESAMPLE*/ | SND_PCM_NO_AUTO_CHANNELS /*| SND_PCM_NO_AUTO_FORMAT*/; snd_pcm_t *pcm; int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_CAPTURE, mode); if (val != 0) { msg_Err (demux, "cannot open ALSA device \"%s\": %s", device, snd_strerror (val)); return VLC_EGENERIC; } sys->pcm = pcm; msg_Dbg (demux, "using ALSA device: %s", device); DumpDevice (VLC_OBJECT(demux), pcm); /* Negotiate capture parameters */ snd_pcm_hw_params_t *hw; es_format_t fmt; unsigned param; int dir; snd_pcm_hw_params_alloca (&hw); snd_pcm_hw_params_any (pcm, hw); Dump (demux, "initial hardware setup:\n", snd_pcm_hw_params_dump, hw); val = snd_pcm_hw_params_set_rate_resample (pcm, hw, 0); if (val) { msg_Err (demux, "cannot disable resampling: %s", snd_strerror (val)); goto error; } val = snd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED); if (val) { msg_Err (demux, "cannot set access mode: %s", snd_strerror (val)); goto error; } snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN; for (size_t i = 0; i < sizeof (choices) / sizeof (choices[0]); i++) if (snd_pcm_hw_params_test_format (pcm, hw, choices[i]) == 0) { val = snd_pcm_hw_params_set_format (pcm, hw, choices[i]); if (val) { msg_Err (demux, "cannot set sample format: %s", snd_strerror (val)); goto error; } format = choices[i]; break; } if (format == SND_PCM_FORMAT_UNKNOWN) { msg_Err (demux, "no supported sample format"); goto error; } assert ((size_t)format < (sizeof (formats) / sizeof (formats[0]))); es_format_Init (&fmt, AUDIO_ES, formats[format]); fmt.audio.i_format = fmt.i_codec; param = 1 + var_InheritBool (demux, "alsa-stereo"); val = snd_pcm_hw_params_set_channels_max (pcm, hw, ¶m); if (val) { msg_Err (demux, "cannot restrict channels count: %s", snd_strerror (val)); goto error; } val = snd_pcm_hw_params_set_channels_last (pcm, hw, ¶m); if (val) { msg_Err (demux, "cannot set channels count: %s", snd_strerror (val)); goto error; } assert (param > 0); assert (param < (sizeof (channel_maps) / sizeof (channel_maps[0]))); fmt.audio.i_channels = param; fmt.audio.i_physical_channels = channel_maps[param - 1]; param = var_InheritInteger (demux, "alsa-samplerate"); val = snd_pcm_hw_params_set_rate_max (pcm, hw, ¶m, NULL); if (val) { msg_Err (demux, "cannot restrict rate to %u Hz or less: %s", 192000, snd_strerror (val)); goto error; } val = snd_pcm_hw_params_set_rate_last (pcm, hw, ¶m, &dir); if (val) { msg_Err (demux, "cannot set sample rate: %s", snd_strerror (val)); goto error; } if (dir) msg_Warn (demux, "sample rate is not integral"); fmt.audio.i_rate = param; sys->rate = param; sys->start = mdate (); sys->caching = INT64_C(1000) * var_InheritInteger (demux, "live-caching"); param = sys->caching; val = snd_pcm_hw_params_set_buffer_time_near (pcm, hw, ¶m, NULL); if (val) { msg_Err (demux, "cannot set buffer duration: %s", snd_strerror (val)); goto error; } param /= 4; val = snd_pcm_hw_params_set_period_time_near (pcm, hw, ¶m, NULL); if (val) { msg_Err (demux, "cannot set period: %s", snd_strerror (val)); goto error; } val = snd_pcm_hw_params_get_period_size (hw, &sys->period_size, &dir); if (val) { msg_Err (demux, "cannot get period size: %s", snd_strerror (val)); goto error; } if (dir > 0) sys->period_size++; /* Commit hardware parameters */ val = snd_pcm_hw_params (pcm, hw); if (val) { msg_Err (demux, "cannot commit hardware parameters: %s", snd_strerror (val)); goto error; } Dump (demux, "final HW setup:\n", snd_pcm_hw_params_dump, hw); /* Kick recording */ aout_FormatPrepare (&fmt.audio); sys->es = es_out_Add (demux->out, &fmt); demux->p_sys = sys; if (vlc_clone (&sys->thread, Thread, demux, VLC_THREAD_PRIORITY_INPUT)) { es_out_Del (demux->out, sys->es); goto error; } demux->pf_demux = NULL; demux->pf_control = Control; return VLC_SUCCESS; error: snd_pcm_close (pcm); return VLC_EGENERIC; }
bool QAudioOutputPrivate::open() { if(opened) return true; #ifdef DEBUG_AUDIO QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; #endif timeStamp.restart(); elapsedTimeOffset = 0; int dir; int err=-1; int count=0; unsigned int freakuency=settings.frequency(); QString dev = QLatin1String(m_device.constData()); QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput); if(dev.compare(QLatin1String("default")) == 0) { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(devices.first().constData()); #else dev = QLatin1String("hw:0,0"); #endif } else { #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) dev = QLatin1String(m_device); #else int idx = 0; char *name; QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData()); while(snd_card_get_name(idx,&name) == 0) { if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0) break; idx++; } dev = QString(QLatin1String("hw:%1,0")).arg(idx); #endif } // Step 1: try and open the device while((count < 5) && (err < 0)) { err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); if(err < 0) count++; } if (( err < 0)||(handle == 0)) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; return false; } snd_pcm_nonblock( handle, 0 ); // Step 2: Set the desired HW parameters. snd_pcm_hw_params_alloca( &hwparams ); bool fatal = false; QString errMessage; unsigned int chunks = 8; err = snd_pcm_hw_params_any( handle, hwparams ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_any: err = %1").arg(err); } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_access( handle, hwparams, access ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_access: err = %1").arg(err); } } if ( !fatal ) { err = setFormat(); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_format: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_channels: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 ); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err); } } if ( !fatal ) { err = snd_pcm_hw_params(handle, hwparams); if ( err < 0 ) { fatal = true; errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params: err = %1").arg(err); } } if( err < 0) { qWarning()<<errMessage; errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; return false; } snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames); buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames); snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir); period_size = snd_pcm_frames_to_bytes(handle,period_frames); snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir); snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir); // Step 3: Set the desired SW parameters. snd_pcm_sw_params_t *swparams; snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(handle, swparams); snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames); snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames); snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames); snd_pcm_sw_params(handle, swparams); // Step 4: Prepare audio if(audioBuffer == 0) audioBuffer = new char[snd_pcm_frames_to_bytes(handle,buffer_frames)]; snd_pcm_prepare( handle ); snd_pcm_start(handle); // Step 5: Setup callback and timer fallback snd_async_add_pcm_handler(&ahandler, handle, async_callback, this); bytesAvailable = bytesFree(); // Step 6: Start audio processing timer->start(period_time/1000); clockStamp.restart(); timeStamp.restart(); elapsedTimeOffset = 0; errorState = QAudio::NoError; totalTimeValue = 0; opened = true; return true; }
int main(int argc, char *argv[]) { int32_t dwLoopsToRecord; int32_t dwStatus; int32_t dwAudioBufferSize; snd_pcm_t *AlsaHandle; snd_pcm_hw_params_t *AlsaParams; uint32_t dwSamplingRate; int32_t dwDirection; snd_pcm_uframes_t AlsaFrames; int8_t *bAudioBuffer; uint32_t dwChannels; wave_t WavFile; /* confirm there are enough parameters */ if(argc < 4) { printf("Usage: alsa_record <interface> <sampling_rate> <channels>"); exit(1); } printf("Alsa Record Opening device: %s\n",argv[1]); /* Open PCM device for recording (capture). */ dwStatus = snd_pcm_open(&AlsaHandle, argv[1], SND_PCM_STREAM_CAPTURE, 0); if (dwStatus < 0) { fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(dwStatus)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(&AlsaParams); /* Fill it in with default values. */ snd_pcm_hw_params_any(AlsaHandle, AlsaParams); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(AlsaHandle, AlsaParams, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(AlsaHandle, AlsaParams, SND_PCM_FORMAT_S16_LE); /* Get the channels from the parameter */ dwChannels = atoi(argv[3]); printf("Alsa Record Recording %d channels\n",dwChannels); /* assign the channels for the wav file */ WavFile.wChannels = dwChannels; /* set channels to ALSA */ snd_pcm_hw_params_set_channels(AlsaHandle, AlsaParams, dwChannels); /* bits/second sampling rate */ dwSamplingRate = atoi(argv[2]); printf("Alsa Record Sampling rate: %i\n", dwSamplingRate); /* Set the sampling rate for the wav file */ WavFile.dwSampleRate = dwSamplingRate; /* Set the sampling rate to ASLA */ snd_pcm_hw_params_set_rate_near(AlsaHandle, AlsaParams, &dwSamplingRate, &dwDirection); /* Set period size to 32 frames. */ AlsaFrames = 32; snd_pcm_hw_params_set_period_size_near(AlsaHandle, AlsaParams, &AlsaFrames, &dwDirection); /* Write the parameters to the driver */ dwStatus = snd_pcm_hw_params(AlsaHandle, AlsaParams); if (dwStatus < 0) { fprintf(stderr,"unable to set hw parameters: %s\n",snd_strerror(dwStatus)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(AlsaParams, &AlsaFrames, &dwDirection); /* 2 bytes/sample, 2 channels */ dwAudioBufferSize = AlsaFrames * 2 * dwChannels; bAudioBuffer = (int8_t *) malloc(dwAudioBufferSize); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(AlsaParams, &dwSamplingRate, &dwDirection); /* Will record 5 seconds, get the amount of frames required */ dwLoopsToRecord = TIME_TO_RECORD_IN_US / dwSamplingRate; printf("SoundCard enabled and configured...\n"); printf("Opening output file\n"); /* Open the file and configure the wav header */ WavFile.dwWaveFileDescriptor = open("audio_mic.wav", O_WRONLY|O_CREAT,S_IRUSR|S_IRGRP|S_IROTH); WavFile.dwSeconds = TIME_TO_RECORD_IN_S; WavBuilder_vfnSetHeader(&WavFile); printf("Recording\n"); while (dwLoopsToRecord) { dwLoopsToRecord--; /* Read an audio frame */ dwStatus = snd_pcm_readi(AlsaHandle, bAudioBuffer, AlsaFrames); if (dwStatus == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(AlsaHandle); } else if (dwStatus < 0) { fprintf(stderr,"error from read: %s\n",snd_strerror(dwStatus)); } else if (dwStatus != (int32_t)AlsaFrames) { fprintf(stderr, "short read, read %d AlsaFrames\n", dwStatus); } /* Take the buffer and write it to the file */ WavBuilder_vfnWriteData(&WavFile,bAudioBuffer, dwAudioBufferSize); } printf("Done\n"); /* Once everything is done, close and release all resources */ snd_pcm_drain(AlsaHandle); snd_pcm_close(AlsaHandle); close(WavFile.dwWaveFileDescriptor); free(bAudioBuffer); return 0; }
static void *alsa_thread_init(const char *device, unsigned rate, unsigned latency) { snd_pcm_uframes_t buffer_size; snd_pcm_format_t format; snd_pcm_hw_params_t *params = NULL; snd_pcm_sw_params_t *sw_params = NULL; const char *alsa_dev = device ? device : "default"; unsigned latency_usec = latency * 1000 / 2; unsigned channels = 2; unsigned periods = 4; alsa_thread_t *alsa = (alsa_thread_t*) calloc(1, sizeof(alsa_thread_t)); if (!alsa) return NULL; TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, 0)); TRY_ALSA(snd_pcm_hw_params_malloc(¶ms)); alsa->has_float = alsathread_find_float_format(alsa->pcm, params); format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16; TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params)); TRY_ALSA(snd_pcm_hw_params_set_access( alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED)); TRY_ALSA(snd_pcm_hw_params_set_format(alsa->pcm, params, format)); TRY_ALSA(snd_pcm_hw_params_set_channels(alsa->pcm, params, channels)); TRY_ALSA(snd_pcm_hw_params_set_rate(alsa->pcm, params, rate, 0)); TRY_ALSA(snd_pcm_hw_params_set_buffer_time_near( alsa->pcm, params, &latency_usec, NULL)); TRY_ALSA(snd_pcm_hw_params_set_periods_near( alsa->pcm, params, &periods, NULL)); TRY_ALSA(snd_pcm_hw_params(alsa->pcm, params)); /* Shouldn't have to bother with this, * but some drivers are apparently broken. */ if (snd_pcm_hw_params_get_period_size(params, &alsa->period_frames, NULL)) snd_pcm_hw_params_get_period_size_min( params, &alsa->period_frames, NULL); RARCH_LOG("ALSA: Period size: %d frames\n", (int)alsa->period_frames); if (snd_pcm_hw_params_get_buffer_size(params, &buffer_size)) snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size); RARCH_LOG("ALSA: Buffer size: %d frames\n", (int)buffer_size); alsa->buffer_size = snd_pcm_frames_to_bytes(alsa->pcm, buffer_size); alsa->period_size = snd_pcm_frames_to_bytes(alsa->pcm, alsa->period_frames); TRY_ALSA(snd_pcm_sw_params_malloc(&sw_params)); TRY_ALSA(snd_pcm_sw_params_current(alsa->pcm, sw_params)); TRY_ALSA(snd_pcm_sw_params_set_start_threshold( alsa->pcm, sw_params, buffer_size / 2)); TRY_ALSA(snd_pcm_sw_params(alsa->pcm, sw_params)); snd_pcm_hw_params_free(params); snd_pcm_sw_params_free(sw_params); alsa->fifo_lock = slock_new(); alsa->cond_lock = slock_new(); alsa->cond = scond_new(); alsa->buffer = fifo_new(alsa->buffer_size); if (!alsa->fifo_lock || !alsa->cond_lock || !alsa->cond || !alsa->buffer) goto error; alsa->worker_thread = sthread_create(alsa_worker_thread, alsa); if (!alsa->worker_thread) { RARCH_ERR("error initializing worker thread"); goto error; } return alsa; error: RARCH_ERR("ALSA: Failed to initialize...\n"); if (params) snd_pcm_hw_params_free(params); if (sw_params) snd_pcm_sw_params_free(sw_params); alsa_thread_free(alsa); return NULL; }
int main() { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; char *buffer; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0); if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, 2); /* 44100 bits/second sampling rate (CD quality) */ val = 44100; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ frames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; /* 2 bytes/sample, 2 channels */ buffer = (char *) malloc(size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 5000000 / val; while (loops > 0) { loops--; rc = snd_pcm_readi(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int) frames) { fprintf(stderr, "short read, read %d frames\n", rc); } rc = write(1, buffer, size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes\n", rc); } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); return 0; }