/** Fill buffers, for starting and stopping * Alsa won't start playing until everything is filled up * This also updates mmap_pos * * Returns: Amount of periods in use so snd_pcm_avail_update * doesn't have to be called up to 4x in GetPosition() */ static snd_pcm_uframes_t CommitAll(IDsDriverBufferImpl *This) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t used; const snd_pcm_uframes_t commitahead = This->mmap_commitahead; used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); TRACE("%p needs to commit to %lu, used: %lu\n", This, commitahead, used); if (used < commitahead) { snd_pcm_uframes_t done, putin = commitahead - used; snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); This->mmap_pos += done; used += done; putin = commitahead - used; if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0) { snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); This->mmap_pos += done; used += done; } } if (This->mmap_pos == This->mmap_buflen_frames) This->mmap_pos = 0; return used; }
/** Fill buffers, for starting and stopping * Alsa won't start playing until everything is filled up * This also updates mmap_pos * * Returns: Amount of periods in use so snd_pcm_avail_update * doesn't have to be called up to 4x in GetPosition() */ static snd_pcm_uframes_t CommitAll(IDsDriverBufferImpl *This) { const snd_pcm_channel_area_t *areas; snd_pcm_sframes_t used; const snd_pcm_uframes_t commitahead = This->mmap_commitahead; used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); if (used < 0) used = 0; TRACE("%p needs to commit to %lu, used: %ld\n", This, commitahead, used); if (used < commitahead) { snd_pcm_sframes_t done; snd_pcm_uframes_t putin = commitahead - used; if (This->mmap) { snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); } else { if (putin + This->mmap_pos > This->mmap_buflen_frames) putin = This->mmap_buflen_frames - This->mmap_pos; done = snd_pcm_writei(This->pcm, This->mmap_buffer + snd_pcm_frames_to_bytes(This->pcm, This->mmap_pos), putin); if (done < putin) WARN("Short write %ld/%ld\n", putin, done); } if (done < 0) done = 0; This->mmap_pos += done; used += done; putin = commitahead - used; if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0) { if (This->mmap) { snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); This->mmap_pos += done; } else { done = snd_pcm_writei(This->pcm, This->mmap_buffer, putin); if (done < putin) WARN("Short write %ld/%ld\n", putin, done); if (done < 0) done = 0; This->mmap_pos = done; } used += done; } } if (This->mmap_pos == This->mmap_buflen_frames) This->mmap_pos = 0; return used; }
static snd_pcm_sframes_t snd_pcm_ioplug_avail_update(snd_pcm_t *pcm) { ioplug_priv_t *io = pcm->private_data; snd_pcm_uframes_t avail; snd_pcm_ioplug_hw_ptr_update(pcm); if (io->data->state == SNDRV_PCM_STATE_XRUN) return -EPIPE; if (pcm->stream == SND_PCM_STREAM_CAPTURE && pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED && pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) { if (io->data->callback->transfer) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t offset, size = UINT_MAX; snd_pcm_sframes_t result; snd_pcm_mmap_begin(pcm, &areas, &offset, &size); result = io->data->callback->transfer(io->data, areas, offset, size); if (result < 0) return result; } } avail = snd_pcm_mmap_avail(pcm); if (avail > io->avail_max) io->avail_max = avail; return (snd_pcm_sframes_t)avail; }
static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t avail; snd_pcm_format_t format; IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface; TRACE("(%p)\n",iface); /* **** */ EnterCriticalSection(&This->pcm_crst); avail = This->mmap_buflen_frames; snd_pcm_drop(This->pcm); snd_pcm_prepare(This->pcm); avail = snd_pcm_avail_update(This->pcm); snd_pcm_hw_params_get_format(This->hw_params, &format); if (This->mmap) { snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &avail); snd_pcm_format_set_silence(format, areas->addr, This->mmap_buflen_frames); snd_pcm_mmap_commit(This->pcm, This->mmap_pos, 0); } else { snd_pcm_format_set_silence(format, This->mmap_buffer, This->mmap_buflen_frames); snd_pcm_writei(This->pcm, This->mmap_buffer, This->mmap_buflen_frames); This->mmap_pos = 0; } /* **** */ LeaveCriticalSection(&This->pcm_crst); return DS_OK; }
static int alsamm_get_channels(snd_pcm_t *dev, snd_pcm_uframes_t *avail, snd_pcm_uframes_t *offset, int nchns, char **addr) { int err = 0; int chn; const snd_pcm_channel_area_t *mm_areas; if (nchns > 0 && avail != NULL && offset != NULL) { if ((err = snd_pcm_mmap_begin(dev, &mm_areas, offset, avail)) < 0){ check_error(err,"setmems: begin_mmap failure ???"); return err; } for (chn = 0; chn < nchns; chn++) { const snd_pcm_channel_area_t *a = &mm_areas[chn]; addr[chn] = (char *) a->addr + ((a->first + a->step * *offset) / 8); } return err; } return -1; }
static snd_pcm_sframes_t snd_pcm_mmap_read_areas(snd_pcm_t *pcm, const snd_pcm_channel_area_t *areas, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { snd_pcm_uframes_t xfer = 0; if (snd_pcm_mmap_capture_avail(pcm) < size) { SNDMSG("too short avail %ld to size %ld", snd_pcm_mmap_capture_avail(pcm), size); return -EPIPE; } while (size > 0) { const snd_pcm_channel_area_t *pcm_areas; snd_pcm_uframes_t pcm_offset; snd_pcm_uframes_t frames = size; snd_pcm_sframes_t result; snd_pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames); snd_pcm_areas_copy(areas, offset, pcm_areas, pcm_offset, pcm->channels, frames, pcm->format); result = snd_pcm_mmap_commit(pcm, pcm_offset, frames); if (result < 0) return xfer > 0 ? (snd_pcm_sframes_t)xfer : result; offset += result; xfer += result; size -= result; } return (snd_pcm_sframes_t)xfer; }
static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface, LPVOID pvAudio1,DWORD dwLen1, LPVOID pvAudio2,DWORD dwLen2) { IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface; snd_pcm_uframes_t writepos; if (!dwLen1) return DS_OK; /* **** */ EnterCriticalSection(&This->pcm_crst); writepos = snd_pcm_bytes_to_frames(This->pcm, (DWORD_PTR)pvAudio1 - (DWORD_PTR)This->mmap_buffer); if (writepos == This->mmap_pos) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen1); TRACE("Committing data\n"); This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen); if (This->mmap_pos == This->mmap_buflen_frames) This->mmap_pos = 0; if (!This->mmap_pos && dwLen2) { writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen2); snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &writelen); This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen); assert(This->mmap_pos < This->mmap_buflen_frames); } } LeaveCriticalSection(&This->pcm_crst); /* **** */ return DS_OK; }
static HRESULT WINAPI IDsDriverBufferImpl_Lock(PIDSDRIVERBUFFER iface, LPVOID*ppvAudio1,LPDWORD pdwLen1, LPVOID*ppvAudio2,LPDWORD pdwLen2, DWORD dwWritePosition,DWORD dwWriteLen, DWORD dwFlags) { IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface; snd_pcm_uframes_t writepos; TRACE("%d bytes from %d\n", dwWriteLen, dwWritePosition); /* **** */ EnterCriticalSection(&This->pcm_crst); if (dwFlags & DSBLOCK_ENTIREBUFFER) dwWriteLen = This->mmap_buflen_bytes; if (dwWriteLen > This->mmap_buflen_bytes || dwWritePosition >= This->mmap_buflen_bytes) { /* **** */ LeaveCriticalSection(&This->pcm_crst); return DSERR_INVALIDPARAM; } if (ppvAudio2) *ppvAudio2 = NULL; if (pdwLen2) *pdwLen2 = 0; *ppvAudio1 = This->mmap_buffer + dwWritePosition; *pdwLen1 = dwWriteLen; if (dwWritePosition+dwWriteLen > This->mmap_buflen_bytes) { DWORD remainder = This->mmap_buflen_bytes - dwWritePosition; *pdwLen1 = remainder; if (ppvAudio2 && pdwLen2) { *ppvAudio2 = This->mmap_buffer; *pdwLen2 = dwWriteLen - remainder; } else dwWriteLen = remainder; } writepos = snd_pcm_bytes_to_frames(This->pcm, dwWritePosition); if (writepos == This->mmap_pos) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t writelen = snd_pcm_bytes_to_frames(This->pcm, dwWriteLen), putin = writelen; TRACE("Hit mmap_pos, locking data!\n"); if (This->mmap) snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); } else WARN("mmap_pos (%lu) != writepos (%lu) not locking data!\n", This->mmap_pos, writepos); LeaveCriticalSection(&This->pcm_crst); /* **** */ return DS_OK; }
mp_sint32 AudioDriver_ALSA::start() { const snd_pcm_channel_area_t *my_areas; snd_pcm_uframes_t offset, frames, size; snd_async_handler_t *ahandler; int err; err = snd_async_add_pcm_handler(&ahandler, pcm, async_direct_callback, this); if (err < 0) { fprintf(stderr, "ALSA: Unable to register async handler (%s)\n", snd_strerror(err)); } for (int count = 0; count < 2; count++) { size = period_size; while (size > 0) { frames = size; err = snd_pcm_mmap_begin(pcm, &my_areas, &offset, &frames); if (err < 0) { if ((err = snd_pcm_recover(pcm, err, 0)) < 0) { fprintf(stderr, "ALSA: MMAP begin error: %s\n", snd_strerror(err)); } } // Sanity check if (my_areas->step != 32 && my_areas->first != 0) fprintf(stderr, "ALSA: Unsupported audio format.\n"); memset(static_cast<char*> (my_areas->addr) + offset*4, 0, frames * 4); int commitres = snd_pcm_mmap_commit(pcm, offset, frames); if (err < 0 || (snd_pcm_uframes_t)commitres != frames) { if ((err = snd_pcm_recover(pcm, commitres >= 0 ? -EPIPE : commitres, 0)) < 0) { fprintf(stderr, "ALSA: MMAP commit error: %s\n", snd_strerror(err)); } } size -= frames; } } \ err = snd_pcm_start(pcm); if (err < 0) { fprintf(stderr, "ALSA: Could not start PCM device (%s)\n", snd_strerror(err)); return -1; } deviceHasStarted = true; return 0; }
static snd_pcm_sframes_t snd_pcm_file_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { snd_pcm_file_t *file = pcm->private_data; snd_pcm_uframes_t ofs; snd_pcm_uframes_t siz = size; const snd_pcm_channel_area_t *areas; snd_pcm_sframes_t result; snd_pcm_mmap_begin(file->gen.slave, &areas, &ofs, &siz); assert(ofs == offset && siz == size); result = snd_pcm_mmap_commit(file->gen.slave, ofs, siz); if (result > 0) snd_pcm_file_add_frames(pcm, areas, ofs, result); return result; }
/** * \brief Begin the capture interleaved frame update * \param pcm ordinary PCM handle * \param ring_buffer returned pointer to actual destination area * \param frames returned maximum count of updated frames * \return 0 on success otherwise a negative error code */ int sndo_pcm_cio_ibegin(sndo_pcm_t *pcm, void **ring_buffer, snd_pcm_uframes_t *frames) { int err; const snd_pcm_channel_area_t *areas; err = sndo_pcm_check_setup(pcm); if (err < 0) return err; err = snd_pcm_mmap_begin(pcm->capture, &areas, &pcm->c_offset, frames); if (err < 0) return err; if (*frames < pcm->transfer_block) { frames = 0; } else { *frames -= *frames % pcm->transfer_block; *ring_buffer = (char *)areas->addr + (areas->first / 8) + pcm->c_offset * pcm->samplebytes; } return 0; }
static snd_pcm_sframes_t snd_pcm_ioplug_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { if (pcm->stream == SND_PCM_STREAM_PLAYBACK && pcm->access != SND_PCM_ACCESS_RW_INTERLEAVED && pcm->access != SND_PCM_ACCESS_RW_NONINTERLEAVED) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t ofs, frames = size; snd_pcm_mmap_begin(pcm, &areas, &ofs, &frames); if (ofs != offset) return -EIO; return ioplug_priv_transfer_areas(pcm, areas, offset, frames); } snd_pcm_mmap_appl_forward(pcm, size); return size; }
static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t offset; void *outputptr; s32_t *inputptr; int err; if (alsa.mmap) { snd_pcm_uframes_t alsa_frames = (snd_pcm_uframes_t)out_frames; snd_pcm_avail_update(pcmp); if ((err = snd_pcm_mmap_begin(pcmp, &areas, &offset, &alsa_frames)) < 0) { LOG_WARN("error from mmap_begin: %s", snd_strerror(err)); return -1; } out_frames = (frames_t)alsa_frames; } if (!silence) { // applying cross fade is delayed until this point as mmap_begin can change out_frames if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) { _apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr); } } inputptr = (s32_t *) (silence ? silencebuf : outputbuf->readp); IF_DSD( if (output.dop) { if (silence) { inputptr = (s32_t *) silencebuf_dop; } update_dop((u32_t *) inputptr, out_frames, output.invert && !silence); } ) if (alsa.mmap || alsa.format != NATIVE_FORMAT) {
/** * \brief Begin the playback noninterleaved frame update * \param pcm ordinary PCM handle * \param ring_buffer returned pointer to actual destination area * \param frames returned maximum count of updated frames * \return 0 on success otherwise a negative error code */ int sndo_pcm_pio_nbegin(sndo_pcm_t *pcm, void ***ring_buffer, snd_pcm_uframes_t *frames) { int err; unsigned ch; const snd_pcm_channel_area_t *areas; err = sndo_pcm_check_setup(pcm); if (err < 0) return err; err = snd_pcm_mmap_begin(pcm->playback, &areas, &pcm->p_offset, frames); if (err < 0) return err; if (*frames < pcm->transfer_block) { frames = 0; } else { *frames -= *frames % pcm->transfer_block; for (ch = 0; ch < pcm->channels; ch++) ring_buffer[ch] = areas->addr + (areas->first / 8) + pcm->p_offset * pcm->samplebytes; } return 0; }
static void set_params(void) { snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t buffer_size; int err; size_t n; unsigned int rate; snd_pcm_uframes_t start_threshold, stop_threshold; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_pcm_hw_params_any(handle, params); if (err < 0) { error("Broken configuration for this PCM: no configurations available"); exit(EXIT_FAILURE); } if (mmap_flag) { snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof()); snd_pcm_access_mask_none(mask); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX); err = snd_pcm_hw_params_set_access_mask(handle, params, mask); } else if (interleaved) err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); else err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_NONINTERLEAVED); if (err < 0) { error("Access type not available"); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_format(handle, params, hwparams.format); if (err < 0) { error("Sample format non available"); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels); if (err < 0) { error("Channels count non available"); exit(EXIT_FAILURE); } #if 0 err = snd_pcm_hw_params_set_periods_min(handle, params, 2); assert(err >= 0); #endif rate = hwparams.rate; err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0); assert(err >= 0); if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) { if (!quiet_mode) { char plugex[64]; const char *pcmname = snd_pcm_name(handle); fprintf(stderr, "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n", rate, hwparams.rate); if (! pcmname || strchr(snd_pcm_name(handle), ':')) *plugex = 0; else snprintf(plugex, sizeof(plugex), "(-Dplug:%s)", snd_pcm_name(handle)); fprintf(stderr, " please, try the plug plugin %s\n", plugex); } } rate = hwparams.rate; if (buffer_time == 0 && buffer_frames == 0) { err = snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0); assert(err >= 0); if (buffer_time > 500000) buffer_time = 500000; } if (period_time == 0 && period_frames == 0) { if (buffer_time > 0) period_time = buffer_time / 4; else period_frames = buffer_frames / 4; } if (period_time > 0) err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0); else err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_frames, 0); assert(err >= 0); if (buffer_time > 0) { err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0); } else { err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_frames); } assert(err >= 0); err = snd_pcm_hw_params(handle, params); if (err < 0) { error("Unable to install hw params:"); snd_pcm_hw_params_dump(params, log); exit(EXIT_FAILURE); } snd_pcm_hw_params_get_period_size(params, &chunk_size, 0); snd_pcm_hw_params_get_buffer_size(params, &buffer_size); if (chunk_size == buffer_size) { error("Can't use period equal to buffer size (%lu == %lu)", chunk_size, buffer_size); exit(EXIT_FAILURE); } snd_pcm_sw_params_current(handle, swparams); if (avail_min < 0) n = chunk_size; else n = (double) rate * avail_min / 1000000; err = snd_pcm_sw_params_set_avail_min(handle, swparams, n); if (err < 0) { error("Setting sw params failed\n"); } /* round up to closest transfer boundary */ n = buffer_size; if (start_delay <= 0) { start_threshold = n + (double) rate * start_delay / 1000000; } else start_threshold = (double) rate * start_delay / 1000000; if (start_threshold < 1) start_threshold = 1; if (start_threshold > n) start_threshold = n; err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); assert(err >= 0); if (stop_delay <= 0) stop_threshold = buffer_size + (double) rate * stop_delay / 1000000; else stop_threshold = (double) rate * stop_delay / 1000000; err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); assert(err >= 0); if (snd_pcm_sw_params(handle, swparams) < 0) { error("unable to install sw params:"); snd_pcm_sw_params_dump(swparams, log); exit(EXIT_FAILURE); } if (verbose) snd_pcm_dump(handle, log); bits_per_sample = snd_pcm_format_physical_width(hwparams.format); bits_per_frame = bits_per_sample * hwparams.channels; chunk_bytes = chunk_size * bits_per_frame / 8; audiobuf = realloc(audiobuf, chunk_bytes); if (audiobuf == NULL) { error("not enough memory"); exit(EXIT_FAILURE); } // fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size); /* stereo VU-meter isn't always available... */ if (vumeter == VUMETER_STEREO) { if (hwparams.channels != 2 || !interleaved || verbose > 2) vumeter = VUMETER_MONO; } /* show mmap buffer arragment */ if (mmap_flag && verbose) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t offset; int i; err = snd_pcm_mmap_begin(handle, &areas, &offset, &chunk_size); if (err < 0) { error("snd_pcm_mmap_begin problem: %s", snd_strerror(err)); exit(EXIT_FAILURE); } for (i = 0; i < hwparams.channels; i++) fprintf(stderr, "mmap_area[%i] = %p,%u,%u (%u)\n", i, areas[i].addr, areas[i].first, areas[i].step, snd_pcm_format_physical_width(hwparams.format)); /* not required, but for sure */ snd_pcm_mmap_commit(handle, offset, 0); } buffer_frames = buffer_size; /* for position test */ }
/** Fill buffers, for starting and stopping * Alsa won't start playing until everything is filled up * This also updates mmap_pos * * Returns: Amount of periods in use so snd_pcm_avail_update * doesn't have to be called up to 4x in GetPosition() */ static snd_pcm_uframes_t CommitAll(IDsCaptureDriverBufferImpl *This, DWORD forced) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t used; const snd_pcm_uframes_t commitahead = This->mmap_buflen_frames; used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); TRACE("%p needs to commit to %lu, used: %lu\n", This, commitahead, used); if (used < commitahead && (forced || This->play_looping)) { snd_pcm_uframes_t done, putin = commitahead - used; if (This->mmap) { snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); CopyData(This, This->mmap_pos, putin); done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); This->mmap_pos += done; used += done; putin = commitahead - used; if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0 && This->play_looping) { This->mmap_ofs_bytes += snd_pcm_frames_to_bytes(This->pcm, This->mmap_buflen_frames); This->mmap_ofs_bytes %= This->mmap_buflen_bytes; snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); CopyData(This, This->mmap_pos, putin); done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); This->mmap_pos += done; used += done; } } else { DWORD pos; snd_pcm_sframes_t ret; snd_pcm_uframes_t cap = snd_pcm_bytes_to_frames(This->pcm, This->mmap_buflen_bytes); pos = realpos_to_fakepos(This, This->mmap_pos); if (This->mmap_pos + putin > cap) putin = cap - This->mmap_pos; ret = snd_pcm_readi(This->pcm, This->presented_buffer + pos, putin); if (ret == -EPIPE) { WARN("Underrun occurred\n"); snd_pcm_prepare(This->pcm); ret = snd_pcm_readi(This->pcm, This->presented_buffer + pos, putin); snd_pcm_start(This->pcm); } if (ret < 0) { WARN("Committing data: %ld / %s (%ld)\n", ret, snd_strerror(ret), putin); ret = 0; } This->mmap_pos += ret; used += ret; /* At this point mmap_pos may be >= This->mmap_pos this is harmless * realpos_to_fakepos handles it well, and below it is truncated */ putin = commitahead - used; if (putin > 0) { pos = realpos_to_fakepos(This, This->mmap_pos); ret = snd_pcm_readi(This->pcm, This->presented_buffer + pos, putin); if (ret > 0) { This->mmap_pos += ret; used += ret; } } } } if (This->mmap_pos >= This->mmap_buflen_frames) { This->mmap_ofs_bytes += snd_pcm_frames_to_bytes(This->pcm, This->mmap_buflen_frames); This->mmap_ofs_bytes %= This->mmap_buflen_bytes; This->mmap_pos -= This->mmap_buflen_frames; } return used; }
static ALuint ALSAProc(ALvoid *ptr) { ALCdevice *Device = (ALCdevice*)ptr; alsa_data *data = (alsa_data*)Device->ExtraData; const snd_pcm_channel_area_t *areas = NULL; snd_pcm_uframes_t update_size, num_updates; snd_pcm_sframes_t avail, commitres; snd_pcm_uframes_t offset, frames; char *WritePtr; int err; SetRTPriority(); update_size = Device->UpdateSize; num_updates = Device->NumUpdates; while(!data->killNow) { int state = verify_state(data->pcmHandle); if(state < 0) { ERR("Invalid state detected: %s\n", snd_strerror(state)); aluHandleDisconnect(Device); break; } avail = snd_pcm_avail_update(data->pcmHandle); if(avail < 0) { ERR("available update failed: %s\n", snd_strerror(avail)); continue; } if((snd_pcm_uframes_t)avail > update_size*(num_updates+1)) { WARN("available samples exceeds the buffer size\n"); snd_pcm_reset(data->pcmHandle); continue; } // make sure there's frames to process if((snd_pcm_uframes_t)avail < update_size) { if(state != SND_PCM_STATE_RUNNING) { err = snd_pcm_start(data->pcmHandle); if(err < 0) { ERR("start failed: %s\n", snd_strerror(err)); continue; } } if(snd_pcm_wait(data->pcmHandle, 1000) == 0) ERR("Wait timeout... buffer size too low?\n"); continue; } avail -= avail%update_size; // it is possible that contiguous areas are smaller, thus we use a loop while(avail > 0) { frames = avail; err = snd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames); if(err < 0) { ERR("mmap begin error: %s\n", snd_strerror(err)); break; } WritePtr = (char*)areas->addr + (offset * areas->step / 8); aluMixData(Device, WritePtr, frames); commitres = snd_pcm_mmap_commit(data->pcmHandle, offset, frames); if(commitres < 0 || (commitres-frames) != 0) { ERR("mmap commit error: %s\n", snd_strerror(commitres >= 0 ? -EPIPE : commitres)); break; } avail -= frames; } } return 0; }
int main() { const snd_pcm_channel_area_t *areas; int size; unsigned char *buffer; char *pcm_name; unsigned int rate = 44100; int chan; int rc; unsigned int val; char check; int pcmreturn; //Set PCM stream and handle snd_pcm_t *pcm_handle; snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; //Set HARDWARE parameters snd_pcm_hw_params_t *hwparams; //pcm_name = (char *)malloc(10); pcm_name = "plughw:0,0"; //allocate memory for hardware if(snd_pcm_hw_params_malloc(&hwparams)<0) { fprintf(stderr,"No memory allocated for hardware"); return(-1); } if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", pcm_name); return(-1); } //INITIALIZE HARDWARE WITH CONFIGURATION OF THE SOUNDCARD if(snd_pcm_hw_params_any(pcm_handle,hwparams)<0) { fprintf(stderr,"The hardware device cannot be configured\n"); } //SET FORMAT TO 16 BIT LITTLE ENDIAN snd_pcm_hw_params_set_format(pcm_handle,hwparams,SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(pcm_handle,hwparams,2); /* 44100 bits/second sampling rate (CD quality) */ if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); return(-1); } //SETTING RATE ie SAMPLING FREQUENCY snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0); //SETTING HARDWARE PARAMETERS if(rc=(snd_pcm_hw_params(pcm_handle,hwparams))<0) { fprintf(stderr,"\nCannot set hardware parameters\n"); return -1; } //snd_pcm_uframes_t periodsize = 8192; snd_pcm_uframes_t frames,offset ;//OF TYPE UNSIGNED LONG snd_pcm_sframes_t commitres; frames =32; //SETTING SOME MORE PARAMETERS size = frames*4; //SETTING BUFFER SIZE /*if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize*2)>>2) < 0) { fprintf(stderr, "Error setting buffersize.\n"); return(-1); } */ int first=0;; int err; snd_pcm_sframes_t avail = snd_pcm_avail_update(pcm_handle); printf("\nNumber of frames available is : %d \n",(int)avail); //------------------------------------------------------------------------------------------------------- //<<<<<<<<<<<<<<<<<<<<<<DISPLAYING INFORMATION>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //Buffer size snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*)&val); printf("\nThe buffer size is %d \n",val); //Buffer time snd_pcm_hw_params_get_buffer_time(hwparams, &val,0); printf("\nBuffer time is : %d \n",val); //Period size snd_pcm_hw_params_get_period_size(hwparams,&frames,0); printf("\nperiod size : %d \n",(int)frames); //Periods between buffers err=snd_pcm_mmap_begin(pcm_handle,&areas,&offset,&frames); //Periods between buffer snd_pcm_hw_params_get_periods(hwparams,&val,0); printf("\n Periods between buffer is : %d \n",val); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>. if(err<0) { printf("\nMMAP error\n"); return -1; } else printf("\n%d\n",err); commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames); if(commitres<0) { printf("\nFrames not committed to memory\n"); } int dest = open("sample3.wav",O_RDONLY); if(dest<0) { perror("\nFile could not be opened\n"); return -1; } //int *c = offset; buffer = (unsigned char *)malloc(1000); unsigned long buf = offset; if(read(dest,&offset,1)<0) { perror("\nNo destination for read\n"); return -1; } struct timeval tvbefore,tvafter; gettimeofday(&tvbefore,NULL); while(read(dest,buffer,100)!=0); gettimeofday(&tvafter,NULL); printf("\nTime taken by read() is %09ld \n",tvafter.tv_usec-tvbefore.tv_usec); /* while(1) { if(read(dest,&offset,80)!=0) { //fread(buffer,sizeof(buffer),160,f1); { if(pcmreturn = snd_pcm_mmap_writei(pcm_handle,&offset,80)<0) { snd_pcm_prepare(pcm_handle); printf("\n<<<<<<<Buffer Underrun>>>>>>>>\n"); break; } } } else break; } */ }
static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface, LPVOID pvAudio1,DWORD dwLen1, LPVOID pvAudio2,DWORD dwLen2) { IDsDriverBufferImpl *This = (IDsDriverBufferImpl *)iface; snd_pcm_uframes_t writepos; if (!dwLen1) return DS_OK; /* **** */ EnterCriticalSection(&This->pcm_crst); writepos = snd_pcm_bytes_to_frames(This->pcm, (DWORD_PTR)pvAudio1 - (DWORD_PTR)This->mmap_buffer); if (writepos == This->mmap_pos) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen1); TRACE("Committing data\n"); if (This->mmap) This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen); else { int ret; ret = snd_pcm_writei(This->pcm, pvAudio1, writelen); if (ret == -EPIPE) { WARN("Underrun occurred\n"); wine_snd_pcm_recover(This->pcm, -EPIPE, 1); ret = snd_pcm_writei(This->pcm, pvAudio1, writelen); /* Advance mmap pointer a little to make dsound notice the underrun and respond to it */ if (ret < writelen) WARN("Short write %ld/%d\n", writelen, ret); This->mmap_pos += This->mmap_commitahead + ret; This->mmap_pos %= This->mmap_buflen_frames; } else if (ret > 0) This->mmap_pos += ret; if (ret < 0) WARN("Committing data: %d / %s (%p %ld)\n", ret, snd_strerror(ret), pvAudio1, writelen); } if (This->mmap_pos == This->mmap_buflen_frames) This->mmap_pos = 0; if (dwLen2) { writelen = snd_pcm_bytes_to_frames(This->pcm, dwLen2); if (This->mmap) { snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &writelen); This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, writelen); } else { int ret; ret = snd_pcm_writei(This->pcm, pvAudio2, writelen); if (ret < writelen) WARN("Short write %ld/%d\n", writelen, ret); This->mmap_pos = ret > 0 ? ret : 0; } assert(This->mmap_pos < This->mmap_buflen_frames); } } LeaveCriticalSection(&This->pcm_crst); /* **** */ return DS_OK; }
int main() { char *filename = "44k.wav"; SF_INFO sfinfo; SNDFILE *f; f = sf_open(filename,SFM_READ, &sfinfo); printf("\nCHECK RATE %d \n",sfinfo.samplerate); printf("\nCHECK CHANNELS %d \n",sfinfo.channels); printf("\nNumber of frames %ld \n",sfinfo.frames); int j; snd_pcm_t *pcm_handle; char *pcm_name; unsigned int err; //pcm_name = "default"; pcm_name = "plughw:0,0"; snd_pcm_hw_params_t *hwparams; unsigned int rate = sfinfo.samplerate; unsigned int channels = sfinfo.channels; unsigned int exact_rate; snd_pcm_uframes_t frames, offset; snd_pcm_sframes_t commitres, avail,size=170; const snd_pcm_channel_area_t *areas; unsigned char *ptr[2]; snd_pcm_format_t stream = SND_PCM_FORMAT_S16_LE; err=snd_pcm_open(&pcm_handle,pcm_name,SND_PCM_STREAM_PLAYBACK,0); if(err<0) { perror("\nCannot open PCM device\n"); exit(0); } if(snd_pcm_hw_params_malloc(&hwparams)<0) { perror("\nMemory cannot be allocated\n"); exit(0); } if(snd_pcm_hw_params_any(pcm_handle,hwparams)<0) { perror("\nUnable to set any HW configuration to device\n"); exit(0); } exact_rate = rate; if(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0)<0) { printf("\nUnable to set rate %u instead rate used is %u \n",rate,exact_rate); } rate = exact_rate; printf("\nExact rate is %u \n",rate); if(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels),0) { perror("\nUnable to set channels\n"); exit(0); } if(snd_pcm_hw_params_set_format(pcm_handle, hwparams, stream)<0) { perror("\nUnable to set format\n"); exit(0); } if(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED)<0) { perror("\nUnable to set access\n"); exit(0); } snd_pcm_sframes_t period_size; snd_pcm_hw_params_get_period_size(hwparams, &period_size,0); printf("\nPeriod size is %ld \n",period_size); err = snd_pcm_hw_params(pcm_handle,hwparams); if(err<0) { perror("\nHW params cannot be set\n"); exit(0); } snd_pcm_hw_params_get_period_size(hwparams,&period_size,0); printf("\nObtained Period size = %ld \n",period_size); size = period_size; snd_pcm_hw_params_get_buffer_size(hwparams,&frames); printf("\nObtained buffer size is %ld \n",frames); int ret = open(filename,O_RDONLY); if(ret<0) { perror("\nFile cannot be opened\n"); exit(0); } int k=0; int i; while(1) { k++; if(k==2) { err = snd_pcm_start(pcm_handle); if(err<0) { perror("\nError starting PCM device\n"); exit(1); } } avail = snd_pcm_avail_update(pcm_handle); if(avail<frames) { err = snd_pcm_prepare(pcm_handle); if(err<0) { perror("\nNo frames available\n"); exit(0); } } // printf("\nFrames available %ld\n",avail); size=period_size; while(size>0) { frames = size; err = snd_pcm_mmap_begin(pcm_handle, &areas, &offset, &frames); if(err<0) { perror("\nMMAP cannot assign areas\n"); exit(0); } for(i=0;i<1;i++) { ptr[i] = (unsigned char *)areas[i].addr + areas[i].first/8 + offset*(areas[i].step/8) ; // printf("\nCheck\n"); if(ptr[i]==NULL) { perror("\nPointer cannot point to memory\n"); exit(0); } } for(i=0;i<1;i++) if(read(ret, ptr[i], frames*4)>0) { } else { perror("\nFile cannot be opened\n"); exit(0); } commitres = snd_pcm_mmap_commit(pcm_handle, offset, frames); if(commitres<0) { err = snd_pcm_prepare(pcm_handle); if(err<0) { perror("\nFrames cannot be committed\n"); exit(0); } } else size-=frames; snd_pcm_wait(pcm_handle,1000); }//END OF "while(size>0)" LOOP }//END OF OUTER WHILE LOOP }
bool AlsaSource::WriteMmap () { snd_pcm_channel_area_t *areas = NULL; snd_pcm_uframes_t offset = 0; snd_pcm_uframes_t frames; snd_pcm_sframes_t available_samples; snd_pcm_sframes_t commitres = 0; guint32 channels = GetChannels (); int err = 0; AudioData *data [channels + 1]; if (GetState () != AudioPlaying) { LOG_ALSA ("AlsaSource::WriteMmap (): trying to write when we're not playing (state: %i)\n", GetState ()); return false; } if (!PreparePcm (&available_samples)) return false; if (GetFlag (AudioEnded)) { Underflowed (); return false; } LOG_ALSA_EX ("AlsaSource::WriteMmap (): entering play loop, avail: %" G_GINT64_FORMAT ", sample size: %i\n", (gint64) available_samples, (int) period_size); frames = available_samples; mutex.Lock (); if (!initialized) goto cleanup; err = snd_pcm_mmap_begin (pcm, (const snd_pcm_channel_area_t** ) &areas, &offset, &frames); if (err < 0) { if (!XrunRecovery (err)) { LOG_AUDIO ("AudioPlayer: could not get mmapped memory: %s\n", snd_strerror (err)); goto cleanup; } started = false; } LOG_ALSA_EX ("AlsaSource::WriteMmap (): can write %lu frames, avail: %lu\n", frames, available_samples); for (guint32 channel = 0; channel < channels; channel++) { data [channel] = (AudioData *) g_malloc (sizeof (AudioData)); // pointer to the first sample to write to data [channel]->dest = ((gint8 *) areas [channel].addr) + (areas [channel].first / 8) + offset * areas [channel].step / 8; // distance (in bytes) between samples data [channel]->distance = areas [channel].step / 8; } data [channels] = NULL; frames = WriteFull (data, frames); for (guint32 channel = 0; channel < channels; channel++) { g_free (data [channel]); } commitres = snd_pcm_mmap_commit (pcm, offset, frames); LOG_ALSA_EX ("AlsaSource::WriteMmap (): played %i samples, of %i available samples, result: %i.\n", (int) frames, (int) 0, (int) commitres); if (commitres < 0 || (snd_pcm_uframes_t) commitres != frames) { if (!XrunRecovery (commitres >= 0 ? -EPIPE : commitres)) { LOG_AUDIO ("AudioPlayer: could not commit mmapped memory: %s\n", snd_strerror(err)); commitres = 0; // so that we end up returning false goto cleanup; } started = false; } cleanup: mutex.Unlock (); return commitres > 0; }
int main(int argc, char *argv[]) { int err; struct sniffer_state sts; sts.pcm_name = strdup("plughw:0,0"); sts.stream = SND_PCM_STREAM_PLAYBACK; sts.format = SND_PCM_FORMAT_A_LAW; sts.rate = 8000; // sts.exact_rate; sts.periods = 2; sts.buffer_time = 25000; sts.period_time = 12500; snd_pcm_hw_params_alloca(&sts.hwparams); if (snd_pcm_open(&sts.pcm, sts.pcm_name, sts.stream, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", sts.pcm_name); return(-1); } if (snd_pcm_hw_params_any(sts.pcm, sts.hwparams) < 0) { fprintf(stderr, "Can not configure this PCM device.\n"); return(-1); } if (snd_pcm_hw_params_set_access(sts.pcm, sts.hwparams, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); return(-1); } if (snd_pcm_hw_params_set_format(sts.pcm, sts.hwparams, sts.format) < 0) { fprintf(stderr, "Error setting format.\n"); return(-1); } sts.exact_rate = sts.rate; if (snd_pcm_hw_params_set_rate_near(sts.pcm, sts.hwparams, &sts.exact_rate, 0) < 0) { fprintf(stderr, "Error setting rate.\n"); return(-1); } printf("rate: %d\n", sts.exact_rate); if (sts.rate != sts.exact_rate) { fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n" "==> Using %d Hz instead.\n", sts.rate, sts.exact_rate); } if (snd_pcm_hw_params_set_channels(sts.pcm, sts.hwparams, 1) < 0) { fprintf(stderr, "Error setting channels.\n"); return(-1); } if (snd_pcm_hw_params_set_periods(sts.pcm, sts.hwparams, sts.periods, 0) < 0) { fprintf(stderr, "Error setting periods.\n"); return(-1); } if (snd_pcm_hw_params_set_buffer_time_near(sts.pcm, sts.hwparams, &sts.buffer_time, &sts.dir) < 0) { fprintf(stderr, "Error setting buffersize.\n"); return(-1); } printf("buffer_time set to %d\n", sts.buffer_time); err = snd_pcm_hw_params_get_period_size(sts.hwparams, &sts.period_size, &sts.dir); if (err < 0) { printf("Unable to get period size for playback: %s\n", snd_strerror(err)); return err; } printf("period_size = %d\n", (int)sts.period_size); if (snd_pcm_hw_params(sts.pcm, sts.hwparams) < 0) { fprintf(stderr, "Error setting HW params.\n"); return(-1); } setvbuf(stdout, (char *)NULL, _IONBF, 0); int router_control_fd = open("/dev/visdn/router-control", O_RDWR); if (router_control_fd < 0) { perror("Unable to open router-control"); return 1; } int fd; fd = open("/dev/visdn/streamport", O_RDWR); if (fd < 0) { perror("cannot open /dev/visdn/streamport"); return 1; } struct vsp_ctl vsp_ctl; if (ioctl(fd, VISDN_SP_GET_NODEID, (caddr_t)&vsp_ctl) < 0) { perror("ioctl(VISDN_SP_GET_NODEID)"); return 1; } char node_id[80]; snprintf(node_id, sizeof(node_id), "/sys/%s", vsp_ctl.node_id); struct visdn_connect vc; memset(&vc, 0, sizeof(vc)); strncpy(vc.from_endpoint, argv[1], sizeof(vc.from_endpoint)); strncpy(vc.to_endpoint, node_id, sizeof(vc.to_endpoint)); printf("Connect: %s => %s\n", vc.from_endpoint, vc.to_endpoint); if (ioctl(router_control_fd, VISDN_IOC_CONNECT, (caddr_t) &vc) < 0) { perror("ioctl(VISDN_CONNECT, br=>sp)"); return 1; } int pipeline_id = vc.pipeline_id; memset(&vc, 0, sizeof(vc)); vc.pipeline_id = pipeline_id; if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_OPEN, (caddr_t)&vc) < 0) { perror("ioctl(VISDN_PIPELINE_OPEN, br=>sp)"); return 1; } memset(&vc, 0, sizeof(vc)); vc.pipeline_id = pipeline_id; if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_START, (caddr_t)&vc) < 0) { perror("ioctl(VISDN_PIPELINE_START, br=>sp)"); return 1; } //double phase = 0; const snd_pcm_channel_area_t *my_areas; snd_pcm_uframes_t offset, frames, size; snd_pcm_sframes_t avail, commitres; snd_pcm_state_t state; int first = 1; while (1) { state = snd_pcm_state(sts.pcm); if (state == SND_PCM_STATE_XRUN) { err = xrun_recovery(sts.pcm, -EPIPE); if (err < 0) { printf("XRUN recovery failed: %s\n", snd_strerror(err)); return err; } first = 1; } else if (state == SND_PCM_STATE_SUSPENDED) { err = xrun_recovery(sts.pcm, -ESTRPIPE); if (err < 0) { printf("SUSPEND recovery failed: %s\n", snd_strerror(err)); return err; } } avail = snd_pcm_avail_update(sts.pcm); if (avail < 0) { err = xrun_recovery(sts.pcm, avail); if (err < 0) { printf("avail update failed: %s\n", snd_strerror(err)); return err; } first = 1; continue; } if (avail < sts.period_size) { if (first) { first = 0; err = snd_pcm_start(sts.pcm); if (err < 0) { printf("Start error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } } else { err = snd_pcm_wait(sts.pcm, -1); if (err < 0) { if ((err = xrun_recovery(sts.pcm, err)) < 0) { printf("snd_pcm_wait error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } } continue; } size = sts.period_size; while (size > 0) { frames = size; err = snd_pcm_mmap_begin(sts.pcm, &my_areas, &offset, &frames); if (err < 0) { if ((err = xrun_recovery(sts.pcm, err)) < 0) { printf("MMAP begin avail error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } int r = read(fd, my_areas[0].addr + offset, frames); printf("%d %d %d: ", (int)offset, (int)frames, r); int i; for (i=0; i<r; i++) printf("%02x", *(__u8 *)(my_areas[0].addr + i)); printf("\n"); commitres = snd_pcm_mmap_commit(sts.pcm, offset, frames); if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { if ((err = xrun_recovery(sts.pcm, commitres >= 0 ? -EPIPE : commitres)) < 0) { printf("MMAP commit error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } size -= frames; } } return 0; }
static void async_direct_callback(snd_async_handler_t *ahandler) { snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler); struct sniffer_state *sns = snd_async_handler_get_callback_private(ahandler); const snd_pcm_channel_area_t *my_areas; snd_pcm_uframes_t offset, frames, size; snd_pcm_sframes_t avail, commitres; snd_pcm_state_t state; int first = 0, err; while (1) { state = snd_pcm_state(handle); if (state == SND_PCM_STATE_XRUN) { err = xrun_recovery(handle, -EPIPE); if (err < 0) { printf("XRUN recovery failed: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } else if (state == SND_PCM_STATE_SUSPENDED) { err = xrun_recovery(handle, -ESTRPIPE); if (err < 0) { printf("SUSPEND recovery failed: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } } avail = snd_pcm_avail_update(handle); if (avail < 0) { err = xrun_recovery(handle, avail); if (err < 0) { printf("avail update failed: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; continue; } if (avail < sns->period_size) { if (first) { first = 0; err = snd_pcm_start(handle); if (err < 0) { printf("Start error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } } else { break; } continue; } size = sns->period_size; while (size > 0) { frames = size; err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames); if (err < 0) { if ((err = xrun_recovery(handle, err)) < 0) { printf("MMAP begin avail error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } printf("Callback %d %d\n", (int)offset, (int)frames); int i; for(i=0; i<frames; i++) *(__u8 *)(my_areas[0].addr + offset + i)=i%64; //generate_sine(my_areas, offset, frames, &sns->phase); commitres = snd_pcm_mmap_commit(handle, offset, frames); if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) { printf("MMAP commit error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } first = 1; } size -= frames; } } }
int main() { const snd_pcm_channel_area_t *areas; int size; unsigned char *buffer; char *pcm_name; unsigned int rate = 8000; int chan; int rc; unsigned int val; char check; int pcmreturn; //Set PCM stream and handle snd_pcm_t *pcm_handle; snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; //Set HARDWARE parameters snd_pcm_hw_params_t *hwparams; //pcm_name = (char *)malloc(10); pcm_name = "plughw:0,0"; //allocate memory for hardware if(snd_pcm_hw_params_malloc(&hwparams)<0) { fprintf(stderr,"No memory allocated for hardware"); return(-1); } if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", pcm_name); return(-1); } //INITIALIZE HARDWARE WITH CONFIGURATION OF THE SOUNDCARD if(snd_pcm_hw_params_any(pcm_handle,hwparams)<0) { fprintf(stderr,"The hardware device cannot be configured\n"); } //SET FORMAT TO 16 BIT LITTLE ENDIAN snd_pcm_hw_params_set_format(pcm_handle,hwparams,SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(pcm_handle,hwparams,2); /* 44100 bits/second sampling rate (CD quality) */ if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) { fprintf(stderr, "Error setting access.\n"); return(-1); } //SETTING RATE ie SAMPLING FREQUENCY snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0); //SETTING HARDWARE PARAMETERS if(rc=(snd_pcm_hw_params(pcm_handle,hwparams))<0) { fprintf(stderr,"\nCannot set hardware parameters\n"); return -1; } //snd_pcm_uframes_t periodsize = 8192; snd_pcm_uframes_t frames,offset ;//OF TYPE UNSIGNED LONG snd_pcm_sframes_t commitres; //frames =32; //SETTING SOME MORE PARAMETERS //size = frames*4; //SETTING BUFFER SIZE /*if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize*2)>>2) < 0) { fprintf(stderr, "Error setting buffersize.\n"); return(-1); } */ int first=0;; int err; snd_pcm_sframes_t avail = snd_pcm_avail_update(pcm_handle); printf("\nNumber of frames available is : %d \n",(int)avail); //------------------------------------------------------------------------------------------------------- //<<<<<<<<<<<<<<<<<<<<<<DISPLAYING INFORMATION>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //Buffer size snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*)&val); printf("\nThe buffer size is %d \n",val); //Buffer time snd_pcm_hw_params_get_buffer_time(hwparams, &val,0); printf("\nBuffer time is : %d \n",val); //Period size snd_pcm_hw_params_get_period_size(hwparams,&frames,0); printf("\nperiod size : %d \n",(int)frames); //////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// //<<<<<<<<<<<<<mmap_begin>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> err=snd_pcm_mmap_begin(pcm_handle,&areas,&offset,&frames); //Periods between buffer snd_pcm_hw_params_get_periods(hwparams,&val,0); printf("\n Periods between buffer is : %d \n",val); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>. if(err<0) { printf("\nMMAP error\n"); return -1; } else printf("\n%d\n",err); /* commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames); if(commitres<0) { printf("\nFrames not committed to memory\n"); } */ //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,OPENING FILE>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.... int dest = open("sample3.wav",O_RDONLY); if(dest<0) { perror("\nFile could not be opened\n"); return -1; } //buffer = (unsigned char *)malloc(1000); /* unsigned long buf = offset; if(read(dest,&offset,1)<0) { perror("\nNo destination for read\n"); return -1; } */ /* avail=snd_pcm_avail_update(pcm_handle); printf("\nAvailable frames = %d \n\n",(int)avail); struct timeval tvbefore,tvafter; gettimeofday(&tvbefore,NULL); */ unsigned char *ptr[2]; int i; //unsigned int steps=0; for(i=0;i<2;i++) ptr[i] = (unsigned char*)areas[i].addr + (areas[i].first/8) + offset*(areas[i].step/8); printf("\nOffset of the first sample : %u \n",areas[0].first); printf("\n\nOffset of the memory map is : %u \n",areas[0].step/8); printf("\nAreas start address is : %u \n",areas[0].addr); printf("\nNumber of frames ; %u \n",frames); printf("\n\nPointer before ; %u \n",ptr[0]); long pl; for(pl=0;pl<100000;pl++); if(ptr[1]==NULL) printf("\nNull pointer 1 allocated\n"); if(ptr[0]==NULL) printf("\nNull pointer 0 allocated \n"); int check2=1; snd_pcm_sframes_t size2 =30; while(1) { for(i=0;i<2;i++) { //ptr[i] = (unsigned char*)areas[i].addr + (areas[i].first/8) + offset*(areas[i].step/8); if(read(dest,ptr[i],120)!=0) { if(ptr[i]!=NULL) { if(pcmreturn = snd_pcm_mmap_writei(pcm_handle,ptr[i],size2)<0) { snd_pcm_prepare(pcm_handle); printf("\n<<<<<<<Buffer Underrun>>>>>>>>\n"); break; } // printf("\n%d\n",pcmreturn); ptr[i]+=0; printf("\n%lu\n",ptr[i]); } } else { check2=0; break; } } if(check2==0) break; // l:break; } commitres = snd_pcm_mmap_commit(pcm_handle,offset,frames); if(commitres<0) { printf("\nFrames not committed to memory\n"); } }
void AudioDriver_ALSA::async_direct_callback(snd_async_handler_t *ahandler) { snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler); AudioDriver_ALSA* audioDriver = (AudioDriver_ALSA*) snd_async_handler_get_callback_private(ahandler); const snd_pcm_channel_area_t *my_areas; snd_pcm_uframes_t offset, frames, size; snd_pcm_sframes_t avail, commitres; snd_pcm_state_t state; int first = 0, err; while (1) { state = snd_pcm_state(handle); if (state == SND_PCM_STATE_XRUN) { err = snd_pcm_recover(handle, -EPIPE, 0); if (err < 0) { fprintf(stderr, "ALSA: XRUN recovery failed: %s\n", snd_strerror(err)); } first = 1; } else if (state == SND_PCM_STATE_SUSPENDED) { err = snd_pcm_recover(handle, ESTRPIPE, 0); if (err < 0) { fprintf(stderr, "ALSA: SUSPEND recovery failed: %s\n", snd_strerror(err)); } } avail = snd_pcm_avail_update(handle); if (avail < 0) { err = snd_pcm_recover(handle, avail, 0); if (err < 0) { fprintf(stderr, "ALSA: avail update failed: %s\n", snd_strerror(err)); } first = 1; continue; } if (avail < audioDriver->period_size) { if (first) { first = 0; err = snd_pcm_start(handle); if (err < 0) { fprintf(stderr, "ALSA: Start error: %s\n", snd_strerror(err)); } } else { break; } continue; } frames = audioDriver->period_size; err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames); if (err < 0) { if ((err = snd_pcm_recover(handle, err, 0)) < 0) { fprintf(stderr, "ALSA: MMAP begin avail error: %s\n", snd_strerror(err)); } first = 1; } if(frames != audioDriver->period_size) fprintf(stderr, "ALSA: Invalid buffer size: %lu (should be %lu), skipping..\n", frames, audioDriver->period_size); // Certain audio drivers will periodically request buffers of less than one period when // soft-resampling (ie, not running at native frequency). Milkytracker can't handle this, // and bad things happen - so best to warn the user and not process. // PS - I've disabled soft-resampling for now (see below) so this shouldn't happen. // PPS - The downside is that if the user has the wrong mixer rate, they will get an error // dialog - hopefully they'll read the message on stderr... else audioDriver->fillAudioWithCompensation(static_cast<char*> (my_areas->addr) + offset*4, frames * 2); commitres = snd_pcm_mmap_commit(handle, offset, frames); if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { if ((err = snd_pcm_recover(handle, commitres >= 0 ? -EPIPE : commitres, 0)) < 0) { fprintf(stderr, "ALSA: MMAP commit error: %s\n", snd_strerror(err)); // What now? // exit(1); } first = 1; } } }
/** * Allocate the memory-mapped buffer for direct sound, and set up the * callback. */ static int DSDB_CreateMMAP(IDsDriverBufferImpl* pdbi) { snd_pcm_t *pcm = pdbi->pcm; snd_pcm_format_t format; snd_pcm_uframes_t frames, ofs, avail, psize, boundary; unsigned int channels, bits_per_sample, bits_per_frame; int err, mmap_mode; const snd_pcm_channel_area_t *areas; snd_pcm_hw_params_t *hw_params = pdbi->hw_params; snd_pcm_sw_params_t *sw_params = pdbi->sw_params; void *buf; mmap_mode = snd_pcm_type(pcm); if (mmap_mode == SND_PCM_TYPE_HW) TRACE("mmap'd buffer is a direct hardware buffer.\n"); else if (mmap_mode == SND_PCM_TYPE_DMIX) TRACE("mmap'd buffer is an ALSA dmix buffer\n"); else TRACE("mmap'd buffer is an ALSA type %d buffer\n", mmap_mode); err = snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL); err = snd_pcm_hw_params_get_format(hw_params, &format); err = snd_pcm_hw_params_get_buffer_size(hw_params, &frames); err = snd_pcm_hw_params_get_channels(hw_params, &channels); bits_per_sample = snd_pcm_format_physical_width(format); bits_per_frame = bits_per_sample * channels; if (TRACE_ON(dsalsa)) ALSA_TraceParameters(hw_params, NULL, FALSE); TRACE("format=%s frames=%ld channels=%d bits_per_sample=%d bits_per_frame=%d\n", snd_pcm_format_name(format), frames, channels, bits_per_sample, bits_per_frame); pdbi->mmap_buflen_frames = frames; pdbi->mmap_buflen_bytes = snd_pcm_frames_to_bytes( pcm, frames ); snd_pcm_sw_params_current(pcm, sw_params); snd_pcm_sw_params_set_start_threshold(pcm, sw_params, 0); snd_pcm_sw_params_get_boundary(sw_params, &boundary); snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, boundary); snd_pcm_sw_params_set_silence_threshold(pcm, sw_params, boundary); snd_pcm_sw_params_set_silence_size(pcm, sw_params, 0); snd_pcm_sw_params_set_avail_min(pcm, sw_params, 0); err = snd_pcm_sw_params(pcm, sw_params); avail = snd_pcm_avail_update(pcm); if ((snd_pcm_sframes_t)avail < 0) { ERR("No buffer is available: %s.\n", snd_strerror(avail)); return DSERR_GENERIC; } if (!pdbi->mmap) { buf = pdbi->mmap_buffer = HeapAlloc(GetProcessHeap(), 0, pdbi->mmap_buflen_bytes); if (!buf) return DSERR_OUTOFMEMORY; snd_pcm_format_set_silence(format, buf, pdbi->mmap_buflen_frames); pdbi->mmap_pos = 0; } else { err = snd_pcm_mmap_begin(pcm, &areas, &ofs, &avail); if ( err < 0 ) { ERR("Can't map sound device for direct access: %s/%d\n", snd_strerror(err), err); return DSERR_GENERIC; } snd_pcm_format_set_silence(format, areas->addr, pdbi->mmap_buflen_frames); pdbi->mmap_pos = ofs + snd_pcm_mmap_commit(pcm, ofs, 0); pdbi->mmap_buffer = areas->addr; } TRACE("created mmap buffer of %ld frames (%d bytes) at %p\n", frames, pdbi->mmap_buflen_bytes, pdbi->mmap_buffer); return DS_OK; }
int alsa_async_direct_loop(alsa_dev_t *dev, void *ptr, void (*callback)(snd_async_handler_t *)) { snd_async_handler_t *ahandler; snd_pcm_t *phandle = dev->phandle; snd_pcm_t *chandle = dev->chandle; snd_pcm_uframes_t period_size = dev->period_size; pc_data_t *data = (pc_data_t *) ptr; PartConvMulti *pc = data->pc; const snd_pcm_channel_area_t *my_areas; snd_pcm_uframes_t offset, frames; snd_pcm_sframes_t avail, commitres; int err; err = snd_async_add_pcm_handler(&ahandler, phandle, callback, ptr); if (err < 0) { printf("Unable to register async handler\n"); exit(-1); } do { avail = snd_pcm_avail_update(phandle); if (avail == 0) break; // printf("\nADL: avail_playback == %d\n", avail); frames = period_size; err = snd_pcm_mmap_begin(phandle, &my_areas, &offset, &frames); if (err < 0) { printf("MMAP begin avail error: %s\n", snd_strerror(err)); exit(-1); } if (frames != period_size) { printf("Error: [ADL] frames != period_size (%d != %d) after snd_pcm_mmap_begin()\n", (int)frames, (int)period_size); exit(-1); } commitres = snd_pcm_mmap_commit(phandle, offset, frames); if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { printf("MMAP commit error: %s\n", snd_strerror(err)); exit(-1); } avail = snd_pcm_avail_update(phandle); } while (1); do { avail = snd_pcm_avail_update(chandle); if (avail == 0) break; // printf("\nADL: avail_capture == %d\n", avail); frames = period_size; err = snd_pcm_mmap_begin(chandle, &my_areas, &offset, &frames); if (err < 0) { printf("MMAP begin avail error: %s\n", snd_strerror(err)); exit(-1); } if (frames != period_size) { printf("Error: [ADL] frames != period_size (%d != %d) after snd_pcm_mmap_begin()\n", (int)frames, (int)period_size); exit(-1); } commitres = snd_pcm_mmap_commit(chandle, offset, frames); if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) { printf("MMAP commit error: %s\n", snd_strerror(err)); exit(-1); } avail = snd_pcm_avail_update(chandle); } while (1); printf("About to start playback.\n"); err = snd_pcm_start(phandle); if (err < 0) { printf("Playback start error: %s\n", snd_strerror(err)); exit(-1); } /* because all other work is done in the signal handler, suspend the process */ if (pc->lastFrame == 0) { while(1) { printf("enter to exit: \n"); if (getc(stdin) == '\n') break; } } else { printf("running for %d frames\n", pc->lastFrame); pc->doneWaiter->waitFor(1); } return 0; }
static int setup_buffers( PaAlsaStream *stream, int frames_avail ) { int i; int capture_frames_avail = INT_MAX; int playback_frames_avail = INT_MAX; int common_frames_avail; if( stream->pcm_capture ) { const snd_pcm_channel_area_t *capture_areas; const snd_pcm_channel_area_t *area; snd_pcm_uframes_t frames = frames_avail; /* I do not understand this code fragment yet, it is copied out of the * alsa-devel archives... */ snd_pcm_mmap_begin( stream->pcm_capture, &capture_areas, &stream->capture_offset, &frames); if( stream->capture_interleaved ) { void *interleaved_capture_buffer; area = &capture_areas[0]; interleaved_capture_buffer = ExtractAddress( area, stream->capture_offset ); PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, 0, /* starting at channel 0 */ interleaved_capture_buffer, 0 /* default numInputChannels */ ); } else { /* noninterleaved */ for( i = 0; i < stream->capture_channels; i++ ) { void *noninterleaved_capture_buffer; area = &capture_areas[i]; noninterleaved_capture_buffer = ExtractAddress( area, stream->capture_offset ); PaUtil_SetNonInterleavedInputChannel( &stream->bufferProcessor, i, noninterleaved_capture_buffer); } } capture_frames_avail = frames; } if( stream->pcm_playback ) { const snd_pcm_channel_area_t *playback_areas; const snd_pcm_channel_area_t *area; snd_pcm_uframes_t frames = frames_avail; snd_pcm_mmap_begin( stream->pcm_playback, &playback_areas, &stream->playback_offset, &frames); if( stream->playback_interleaved ) { void *interleaved_playback_buffer; area = &playback_areas[0]; interleaved_playback_buffer = ExtractAddress( area, stream->playback_offset ); PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, 0, /* starting at channel 0 */ interleaved_playback_buffer, 0 /* default numInputChannels */ ); } else { /* noninterleaved */ for( i = 0; i < stream->playback_channels; i++ ) { void *noninterleaved_playback_buffer; area = &playback_areas[i]; noninterleaved_playback_buffer = ExtractAddress( area, stream->playback_offset ); PaUtil_SetNonInterleavedOutputChannel( &stream->bufferProcessor, i, noninterleaved_playback_buffer); } } playback_frames_avail = frames; } common_frames_avail = MIN(capture_frames_avail, playback_frames_avail); common_frames_avail -= common_frames_avail % stream->frames_per_period; //PA_DEBUG(( "%d capture frames available\n", capture_frames_avail )); //PA_DEBUG(( "%d frames playback available\n", playback_frames_avail )); //PA_DEBUG(( "%d frames available\n", common_frames_avail )); if( stream->pcm_capture ) PaUtil_SetInputFrameCount( &stream->bufferProcessor, common_frames_avail ); if( stream->pcm_playback ) PaUtil_SetOutputFrameCount( &stream->bufferProcessor, common_frames_avail ); return common_frames_avail; }