void QAudioOutputPrivate::resume()
{
    if(deviceState == QAudio::SuspendedState) {
        int err = 0;

        if(handle) {
            err = snd_pcm_prepare( handle );
            if(err < 0)
                xrun_recovery(err);

            err = snd_pcm_start(handle);
            if(err < 0)
                xrun_recovery(err);

            bytesAvailable = (int)snd_pcm_frames_to_bytes(handle, buffer_frames);
        }
        resuming = true;
        if(pullMode)
            deviceState = QAudio::ActiveState;
        else
            deviceState = QAudio::IdleState;

        errorState = QAudio::NoError;
        timer->start(period_time/1000);
        emit stateChanged(deviceState);
    }
}
示例#2
0
static void ALSA_Update(void)
{
	int err;

	if (!enabled) return;

	if (bytes_written == 0 || bytes_played == bytes_written) {
		bytes_written = VC_WriteBytes(audiobuffer,period_size * global_frame_size);
		bytes_played = 0;
	}

	while (bytes_played < bytes_written)
	{
		err = alsa_pcm_writei(pcm_h, &audiobuffer[bytes_played], (bytes_written - bytes_played) / global_frame_size);
		if (err == -EAGAIN)
			continue;
		if (err < 0) {
			if ((err = xrun_recovery(pcm_h, err)) < 0) {
				_mm_errno = MMERR_ALSA_PCM_RECOVER;
				enabled = 0;
				dbgprint(stderr, "Write error: %s\n", alsa_strerror(err));
			}
			break;
		}
		bytes_played += err * global_frame_size;
	}
}
示例#3
0
文件: pcm.c 项目: chenzhongtao/source
static int write_loop(snd_pcm_t *handle,
                      signed short *samples,
                      snd_pcm_channel_area_t *areas)
{
        double phase = 0;
        signed short *ptr;
        int err, cptr;

        while (1) {
                generate_sine(areas, 0, period_size, &phase);
                ptr = samples;
                cptr = period_size;
                while (cptr > 0) {
                        err = snd_pcm_writei(handle, ptr, cptr);
                        if (err == -EAGAIN)
                                continue;
                        if (err < 0) {
                                if (xrun_recovery(handle, err) < 0) {
                                        printf("Write error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                break;  /* skip one period */
                        }
                        ptr += err * channels;
                        cptr -= err;
                }
        }
}
示例#4
0
/* alsa_update:
 *  Updates main buffer in case ALSA is ready.
 */
static void alsa_update(int threaded)
{
   unsigned short revents;

   if (poll_next) {
      poll(ufds, pdc, 0);
      snd_pcm_poll_descriptors_revents(pcm_handle, ufds, pdc, &revents);
      if (revents & POLLERR) {
	 if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN ||
	    snd_pcm_state(pcm_handle) == SND_PCM_STATE_SUSPENDED) {
	    int err = snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
	    if (xrun_recovery(pcm_handle, err) < 0) {
	       fprintf(stderr, "Write error: %s\n", snd_strerror(err));
	    }
	    poll_next = 0;
         }
	 else {
	    fprintf(stderr, "Wait for poll failed\n");
	 }
         return;
      }
      if (!(revents & POLLOUT))
	 return;
   }
   alsa_mix();
}
示例#5
0
static guint
gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
{
    GstAlsaSink *alsa;
    gint err;
    gint cptr;
    gint16 *ptr = data;

    alsa = GST_ALSA_SINK (asink);

    if (alsa->iec958 && alsa->need_swap) {
        guint i;

        GST_DEBUG_OBJECT (asink, "swapping bytes");
        for (i = 0; i < length / 2; i++) {
            ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]);
        }
    }

    GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);

    cptr = length / alsa->bytes_per_sample;

    GST_ALSA_SINK_LOCK (asink);
    while (cptr > 0) {
        /* start by doing a blocking wait for free space. Set the timeout
         * to 4 times the period time */
        err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
        if (err < 0) {
            GST_DEBUG_OBJECT (asink, "wait error, %d", err);
        } else {
            GST_DELAY_SINK_LOCK (asink);
            err = snd_pcm_writei (alsa->handle, ptr, cptr);
            GST_DELAY_SINK_UNLOCK (asink);
        }

        GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
        if (err < 0) {
            GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
            if (err == -EAGAIN) {
                continue;
            } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
                goto write_error;
            }
            continue;
        }

        ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
        cptr -= err;
    }
    GST_ALSA_SINK_UNLOCK (asink);

    return length - (cptr * alsa->bytes_per_sample);

write_error:
    {
        GST_ALSA_SINK_UNLOCK (asink);
        return length;              /* skip one period */
    }
}
示例#6
0
static void ALSA_Update(void)
{
    int err;

    {
        if (bytes_written == 0 || bytes_played == bytes_written)
        {
            bytes_written = VC_WriteBytes(audiobuffer,buffer_size_in_frames * global_frame_size);
            bytes_played = 0;
        }

        while (bytes_played < bytes_written)
        {
            err = alsa_pcm_writei(pcm_h, &audiobuffer[bytes_played], (bytes_written - bytes_played) / global_frame_size);
            if (err == -EAGAIN)
            {
                continue;
            }
            if (err < 0) {
                if ((err = xrun_recovery(pcm_h, err)) < 0) {
                    printf("Write error: %s\n", alsa_strerror(err));
                    exit(-1);
                }
                break;
            }
            bytes_played += err * global_frame_size;
        }
    }
}
示例#7
0
    void write( const char *data, qint64 len )
    {
        if ( !handle )
            return;

        int count=0;

        qLog(QAudioOutput)<<"frames to write out = "<<
            snd_pcm_bytes_to_frames( handle, (int)len )<<" ("<<len<<") bytes";

        while ( len > 0 ) {

            int err=0;
            int frames = snd_pcm_bytes_to_frames( handle, (int)len );

#ifdef ALSA_USE_AVAILABLE
            if(frames < (int)period_size)
                return;

            int available = snd_pcm_avail_update(handle);
            qLog(QAudioOutput) <<"available space = "<<available;
            if(available == 0) {
                while(available < frames) {
                    snd_pcm_wait(handle,period_size/1000);
                    usleep(period_size*10);
                    available = snd_pcm_avail_update(handle);
                    qLog(QAudioOutput) <<"->available space = "<<available;
                    count++;
                    if((count > 5)||(available < 0))
                        return;
                }
            }
#endif

            err = snd_pcm_writei( handle, data, frames );

            // Handle errors
            if ( err >= 0 ) {
                if(err == 0) count++;
                int bytes = snd_pcm_frames_to_bytes( handle, err );
                qLog(QAudioOutput) << QString("write out = %1").arg(bytes).toLatin1().constData();
                data += bytes;
                len -= bytes;
            } else {
                count++;
                qLog(QAudioOutput) <<"err = "<<err;
                err = xrun_recovery(err);
            }
            if(count > 5) {
                qLog(QAudioOutput) <<"failing to write, close() and re-open() to try and recover!";
                close();
                open();
                snd_pcm_prepare(handle);
                break;
            }
        }
    }
示例#8
0
static int verify_state(snd_pcm_t *handle)
{
    snd_pcm_state_t state = psnd_pcm_state(handle);
    if(state == SND_PCM_STATE_DISCONNECTED)
        return -ENODEV;
    if(state == SND_PCM_STATE_XRUN)
    {
        int err = xrun_recovery(handle, -EPIPE);
        if(err < 0) return err;
    }
    else if(state == SND_PCM_STATE_SUSPENDED)
    {
        int err = xrun_recovery(handle, -ESTRPIPE);
        if(err < 0) return err;
    }

    return state;
}
示例#9
0
static GstClockTime
gst_alsasrc_get_timestamp (GstAlsaSrc * asrc)
{
  snd_pcm_status_t *status;
  snd_htimestamp_t tstamp;
  GstClockTime timestamp;
  snd_pcm_uframes_t avail;
  gint err = -EPIPE;

  if (G_UNLIKELY (!asrc)) {
    GST_ERROR_OBJECT (asrc, "No alsa handle created yet !");
    return GST_CLOCK_TIME_NONE;
  }

  if (G_UNLIKELY (snd_pcm_status_malloc (&status) != 0)) {
    GST_ERROR_OBJECT (asrc, "snd_pcm_status_malloc failed");
    return GST_CLOCK_TIME_NONE;
  }

  if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
    GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
    return GST_CLOCK_TIME_NONE;
  }

  /* in case an xrun condition has occured we need to handle this */
  if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING) {
    if (xrun_recovery (asrc, asrc->handle, err) < 0) {
      GST_WARNING_OBJECT (asrc, "Could not recover from xrun condition !");
    }
    /* reload the status alsa status object, since recovery made it invalid */
    if (G_UNLIKELY (snd_pcm_status (asrc->handle, status) != 0)) {
      GST_ERROR_OBJECT (asrc, "snd_pcm_status failed");
    }
  }

  /* get high resolution time stamp from driver */
  snd_pcm_status_get_htstamp (status, &tstamp);
  timestamp = GST_TIMESPEC_TO_TIME (tstamp);

  /* max available frames sets the depth of the buffer */
  avail = snd_pcm_status_get_avail (status);

  /* calculate the timestamp of the next sample to be read */
  timestamp -= gst_util_uint64_scale_int (avail, GST_SECOND, asrc->rate);

  /* compensate for the fact that we really need the timestamp of the
   * previously read data segment */
  timestamp -= asrc->period_time * 1000;

  snd_pcm_status_free (status);

  GST_LOG_OBJECT (asrc, "ALSA timestamp : %" GST_TIME_FORMAT
      ", delay %lu", GST_TIME_ARGS (timestamp), avail);

  return timestamp;
}
示例#10
0
static guint
gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length,
    GstClockTime * timestamp)
{
  GstAlsaSrc *alsa;
  gint err;
  gint cptr;
  guint8 *ptr = data;

  alsa = GST_ALSA_SRC (asrc);

  cptr = length / alsa->bpf;

  GST_ALSA_SRC_LOCK (asrc);
  while (cptr > 0) {
    GST_DELAY_SRC_LOCK (asrc);
    err = snd_pcm_readi (alsa->handle, ptr, cptr);
    GST_DELAY_SRC_UNLOCK (asrc);

    if (err < 0) {
      if (err == -EAGAIN) {
        GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err));
        continue;
      } else if (err == -ENODEV) {
        goto device_disappeared;
      } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
        goto read_error;
      }
      continue;
    }

    ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
    cptr -= err;
  }
  GST_ALSA_SRC_UNLOCK (asrc);

  /* if driver timestamps are enabled we need to return this here */
  if (alsa->driver_timestamps && timestamp)
    *timestamp = gst_alsasrc_get_timestamp (alsa);

  return length - (cptr * alsa->bpf);

read_error:
  {
    GST_ALSA_SRC_UNLOCK (asrc);
    return length;              /* skip one period */
  }
device_disappeared:
  {
    GST_ELEMENT_ERROR (asrc, RESOURCE, READ,
        (_("Error recording from audio device. "
                "The device has been disconnected.")), (NULL));
    GST_ALSA_SRC_UNLOCK (asrc);
    return (guint) - 1;
  }
}
示例#11
0
文件: alsa_play.c 项目: alatagoo/test
static int write_loop(snd_pcm_t *handle)
{
	double phase = 0;
	signed short *ptr;
	int err, cptr;
	

struct async_private_data data;
	snd_async_handler_t *ahandler;

	size_t data_len;
	signed short *samples_buf_play;
	samples_buf_play = malloc(910*2);

	FILE* file_playback = fopen("file_playback","rb");
	FILE* file_dump = fopen("file_dump","wb");
	if(file_playback== NULL)
	{
		printf("file open err check the file please\r\n");
		return 0;
	}

	
	err = snd_async_add_pcm_handler(&ahandler, handle, play_callback, &data);
	if (err < 0) 
	{
		printf("Unable to register async handler\n");
		exit(EXIT_FAILURE);
	}

	while (1)
	 {
		data_len = fread(samples_buf_play,2,910,file_playback);
		fwrite(samples_buf_play,2,data_len,file_dump);
		if(data_len != 910)
		{
			printf("the data is not enough %d\r\n",data_len );
			return 0;
		}
		err = snd_pcm_writei(handle, samples_buf_play,910);
		if (err < 0) 
		{	
			if (xrun_recovery(handle, err) < 0) 
			{
				printf("Write error: %s\n", snd_strerror(err));
				exit(EXIT_FAILURE);
			}
			break; /* skip one period */
		}
	}
}
示例#12
0
static int alsa_bufferspace(void)
{
    int err;
    snd_pcm_sframes_t delay;

    if ((err = snd_pcm_delay(handle, &delay)) < 0) {
	if ((err = xrun_recovery(handle, err)) < 0) {
	    log_message(LOG_DEFAULT, "Delay error: %s", snd_strerror(err));
	}
	return alsa_bufsize;
    }

    return alsa_bufsize - delay;
}
示例#13
0
void QAlsaAudioInput::resume()
{
    if(deviceState == QAudio::SuspendedState) {
        int err = 0;

        if(handle) {
            err = snd_pcm_prepare( handle );
            if(err < 0)
                xrun_recovery(err);

            err = snd_pcm_start(handle);
            if(err < 0)
                xrun_recovery(err);

            bytesAvailable = buffer_size;
        }
        resuming = true;
        deviceState = QAudio::ActiveState;
        int chunks = buffer_size/period_size;
        timer->start(period_time*chunks/2000);
        emit stateChanged(deviceState);
    }
}
示例#14
0
static void *
alsa_thread(void *arg)
{
	gint16 *ptr;
	int err, cptr;
	guint8 *buf;
	sfx_pcm_device_t *self = (sfx_pcm_device_t *) arg;

	buf = (guint8 *) malloc(period_size * frame_size);

	while (run_thread) {
		ptr = (gint16 *) buf;
		cptr = period_size;

		sci_gettime(&last_callback_secs, &last_callback_usecs);

		self->timer->block();

		if (alsa_sfx_timer_callback)
			alsa_sfx_timer_callback(alsa_sfx_timer_data);

		self->timer->unblock();

		sfx_audbuf_read(&audio_buffer, buf, period_size);

		while (cptr > 0) {
			err = snd_pcm_writei(handle, ptr, cptr);
			if (err == -EAGAIN)
				continue;
			if (err < 0) {
				if (xrun_recovery(handle, err) < 0) {
					fprintf(stderr, "[SND:ALSA] Write error: %s\n", snd_strerror(err));
					run_thread = 0;
				}
				break;  /* skip one period */
			}
			ptr += err * channels;
			cptr -= err;
		}
	}

	free(buf);
	return NULL;
}
// returns -1 on error
int DAUDIO_Read(void* id, char* data, int byteSize) {
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
    int ret, count;
    snd_pcm_sframes_t frameSize, readFrames;

    TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
    /*TRACE3("  info=%p, data=%p, byteSize=%d\n",
      (void*) info, (void*) data, (int) byteSize);
      TRACE2("  info->frameSize=%d, info->handle=%p\n",
      (int) info->frameSize, (void*) info->handle);
    */
    /* sanity */
    if (byteSize <= 0 || info->frameSize <= 0) {
        ERROR2(" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
               (int) byteSize, (int) info->frameSize);
        TRACE0("< DAUDIO_Read returning -1\n");
        return -1;
    }
    count = 2; // maximum number of trials to recover from error
    //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
    frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
    do {
        readFrames = snd_pcm_readi(info->handle, (void*) data, (snd_pcm_uframes_t) frameSize);
        if (readFrames < 0) {
            ret = xrun_recovery(info, (int) readFrames);
            if (ret <= 0) {
                TRACE1("DAUDIO_Read: xrun recovery returned %d -> return.\n", ret);
                return ret;
            }
            if (count-- <= 0) {
                ERROR0("DAUDIO_Read: too many attempts to recover from xrun/suspend\n");
                return -1;
            }
        } else {
            break;
        }
    } while (TRUE);
    //ret =  snd_pcm_frames_to_bytes(info->handle, readFrames);
    ret =  (int) (readFrames * info->frameSize);
    TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
    return ret;
}
示例#16
0
qint64 QAudioOutputPrivate::write( const char *data, qint64 len )
{
    // Write out some audio data
    if ( !handle )
        return 0;
#ifdef DEBUG_AUDIO
    qDebug()<<"frames to write out = "<<
            snd_pcm_bytes_to_frames( handle, (int)len )<<" ("<<len<<") bytes";
#endif
    int frames, err;
    int space = bytesFree();
    if(len < space) {
        // Just write it
        frames = snd_pcm_bytes_to_frames( handle, (int)len );
        err = snd_pcm_writei( handle, data, frames );
    } else {
        // Only write space worth
        frames = snd_pcm_bytes_to_frames( handle, (int)space );
        err = snd_pcm_writei( handle, data, frames );
    }
    if(err > 0) {
        totalTimeValue += err;
        resuming = false;
        errorState = QAudio::NoError;
        if (deviceState != QAudio::ActiveState) {
            deviceState = QAudio::ActiveState;
            emit stateChanged(deviceState);
        }
        return snd_pcm_frames_to_bytes( handle, err );
    } else
        err = xrun_recovery(err);

    if(err < 0) {
        close();
        errorState = QAudio::FatalError;
        emit errorChanged(errorState);
        deviceState = QAudio::StoppedState;
        emit stateChanged(deviceState);
    }
    return 0;
}
示例#17
0
static int alsa_write(SWORD *pbuf, size_t nr)
{
    int err;

    nr /= alsa_channels;

    while (nr > 0) {
        err = snd_pcm_writei(handle, pbuf, nr);
        if (err == -EAGAIN) {
            log_message(LOG_DEFAULT, "Write error: %s", snd_strerror(err));
            continue;
        } else if (err < 0 && (err = xrun_recovery(handle, err)) < 0) {
            log_message(LOG_DEFAULT, "Write error: %s", snd_strerror(err));
            return 1;
        }
        pbuf += err * alsa_channels;
        nr -= err;
    }

    return 0;
}
// returns -1 on error
int DAUDIO_Write(void* id, char* data, int byteSize) {
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
    int ret, count;
    snd_pcm_sframes_t frameSize, writtenFrames;

    TRACE1("> DAUDIO_Write %d bytes\n", byteSize);

    /* sanity */
    if (byteSize <= 0 || info->frameSize <= 0) {
        ERROR2(" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
               (int) byteSize, (int) info->frameSize);
        TRACE0("< DAUDIO_Write returning -1\n");
        return -1;
    }
    count = 2; // maximum number of trials to recover from underrun
    //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
    frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
    do {
        writtenFrames = snd_pcm_writei(info->handle, (const void*) data, (snd_pcm_uframes_t) frameSize);

        if (writtenFrames < 0) {
            ret = xrun_recovery(info, (int) writtenFrames);
            if (ret <= 0) {
                TRACE1("DAUDIO_Write: xrun recovery returned %d -> return.\n", ret);
                return ret;
            }
            if (count-- <= 0) {
                ERROR0("DAUDIO_Write: too many attempts to recover from xrun/suspend\n");
                return -1;
            }
        } else {
            break;
        }
    } while (TRUE);
    //ret =  snd_pcm_frames_to_bytes(info->handle, writtenFrames);
    ret =  (int) (writtenFrames * info->frameSize);
    TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
    return ret;
}
示例#19
0
static
int play(struct audio_play *play)
{
    int err, len;
    char *ptr;

    ptr = buf;
    len = play->nsamples;

    audio_pcm(ptr, len, play->samples[0], play->samples[1],
              play->mode, play->stats);

    while (len > 0) {

        err = snd_pcm_mmap_writei(alsa_handle, ptr, len);

        if (err == -EAGAIN)
            continue;

        if (err < 0) {
            if (xrun_recovery(alsa_handle, err) < 0) {
                audio_error = snd_strerror(err);
                return -1;

            }
            break;
        }

        len -= err;
        ptr += err * sample_size;

    }

    return 0;

}
示例#20
0
/* alsa_mix
 *  Mix and send some samples to ALSA.
 */
static void alsa_mix(void)
{
   int ret, samples = alsa_bufsize;
   unsigned char *ptr = alsa_bufdata;

   while (samples > 0) {
      ret = snd_pcm_writei(pcm_handle, ptr, samples);
      if (ret == -EAGAIN)
	 continue;

      if (ret < 0) {
	 if (xrun_recovery(pcm_handle, ret) < 0)
	    fprintf(stderr, "Write error: %s\n", snd_strerror(ret));
	 poll_next = 0;
	 break;  /* skip one period */
      }
      if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_RUNNING)
	 poll_next = 1;
      samples -= ret;
      ptr += ret * alsa_sample_size;
   }

   _mix_some_samples((uintptr_t)alsa_bufdata, 0, alsa_signed);
}
示例#21
0
bool QAlsaAudioInput::deviceReady()
{
    if(pullMode) {
        // reads some audio data and writes it to QIODevice
        read(0, buffer_size);
    } else {
        // emits readyRead() so user will call read() on QIODevice to get some audio data
        AlsaInputPrivate* a = qobject_cast<AlsaInputPrivate*>(audioSource);
        a->trigger();
    }
    bytesAvailable = checkBytesReady();

    if(deviceState != QAudio::ActiveState)
        return true;

    if (bytesAvailable < 0) {
        // bytesAvailable as negative is error code, try to recover from it.
        xrun_recovery(bytesAvailable);
        bytesAvailable = checkBytesReady();
        if (bytesAvailable < 0) {
            // recovery failed must stop and set error.
            close();
            errorState = QAudio::IOError;
            deviceState = QAudio::StoppedState;
            emit stateChanged(deviceState);
            return 0;
        }
    }

    if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
        emit notify();
        elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
        timeStamp.restart();
    }
    return true;
}
示例#22
0
static void *sound_play(void *args)
{
    char path[256];
    int samplerate;
    int err;
    snd_pcm_t *playback_handle;
    snd_pcm_hw_params_t *hw_params;
    FILE *fp;

    db_msg("prepare play sound...\n");
    if (script_fetch("hdmi", "sound_file", (int *)path, sizeof(path) / 4)) {
        db_warn("unknown sound file, use default\n");
        strcpy(path, "/dragonboard/data/test48000.pcm");
    }
    if (script_fetch("hdmi", "samplerate", &samplerate, 1)) {
        db_warn("unknown samplerate, use default #48000\n");
        samplerate = 48000;
    }
    db_msg("samplerate #%d\n", samplerate);

    err = snd_pcm_open(&playback_handle, "hw:1,0", SND_PCM_STREAM_PLAYBACK, 0);
    if (err < 0) {
        db_error("cannot open audio device (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_malloc(&hw_params);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_any(playback_handle, hw_params);
    if (err < 0) {
        db_error("cannot initialize hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
    if (err < 0) {
        db_error("cannot allocate hardware parameter structure (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_rate(playback_handle, hw_params, samplerate, 0);
    if (err < 0) {
        db_error("cannot set sample rate (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params_set_channels(playback_handle, hw_params, 2);
    if (err < 0) {
        db_error("cannot set channel count (%s), err = %d\n", snd_strerror(err), err);
        pthread_exit((void *)-1);
    }

    err = snd_pcm_hw_params(playback_handle, hw_params);
    if (err < 0) {
        db_error("cannot set parameters (%s)\n", snd_strerror(err));
        pthread_exit((void *)-1);
    }

    snd_pcm_hw_params_free(hw_params);

    db_msg("open test pcm file: %s\n", path);
    fp = fopen(path, "r");
    if (fp == NULL) {
        db_error("cannot open test pcm file(%s)\n", strerror(errno));
        pthread_exit((void *)-1);
    }

    db_msg("play it...\n");
    while (1) {
        while (!feof(fp)) {
            if (sound_play_stop) {
                goto out;
            }

            err = fread(buf, 1, BUF_LEN, fp);
            if (err < 0) {
                db_warn("read test pcm failed(%s)\n", strerror(errno));
            }

            err = snd_pcm_writei(playback_handle, buf, BUF_LEN/4);
            if (err < 0) {
                err = xrun_recovery(playback_handle, err);
                if (err < 0) {
                    db_warn("write error: %s\n", snd_strerror(err));
                }
            }

            if (err == -EBADFD) {
                db_warn("PCM is not in the right state (SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING)\n");
            }
            if (err == -EPIPE) {
                db_warn("an underrun occurred\n");
            }
            if (err == -ESTRPIPE) {
                db_warn("a suspend event occurred (stream is suspended and waiting for an application recovery)\n");
            }

            if (feof(fp)) {
                fseek(fp, 0L, SEEK_SET);
            }
        }
    }

out:
    db_msg("play end...\n");
    fclose(fp);
    snd_pcm_close(playback_handle);
    pthread_exit(0);
}
示例#23
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;
}
示例#24
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;
		}
	}
}
示例#25
0
static gint
gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length)
{
  GstAlsaSink *alsa;
  gint err;
  gint cptr;
  guint8 *ptr = data;

  alsa = GST_ALSA_SINK (asink);

  if (alsa->iec958 && alsa->need_swap) {
    guint i;
    guint16 *ptr_tmp = (guint16 *) ptr;

    GST_DEBUG_OBJECT (asink, "swapping bytes");
    for (i = 0; i < length / 2; i++) {
      ptr_tmp[i] = GUINT16_SWAP_LE_BE (ptr_tmp[i]);
    }
  }

  GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length);

  cptr = length / alsa->bpf;

  GST_ALSA_SINK_LOCK (asink);
  while (cptr > 0) {
    /* start by doing a blocking wait for free space. Set the timeout
     * to 4 times the period time */
    err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000));
    if (err < 0) {
      GST_DEBUG_OBJECT (asink, "wait error, %d", err);
    } else {
      GST_DELAY_SINK_LOCK (asink);
      err = snd_pcm_writei (alsa->handle, ptr, cptr);
      GST_DELAY_SINK_UNLOCK (asink);
    }

    GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr);
    if (err < 0) {
      GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err));
      if (err == -EAGAIN) {
        continue;
      } else if (err == -ENODEV) {
        goto device_disappeared;
      } else if (xrun_recovery (alsa, alsa->handle, err) < 0) {
        goto write_error;
      }
      continue;
    }

    ptr += snd_pcm_frames_to_bytes (alsa->handle, err);
    cptr -= err;
  }
  GST_ALSA_SINK_UNLOCK (asink);

  return length - (cptr * alsa->bpf);

write_error:
  {
    GST_ALSA_SINK_UNLOCK (asink);
    return length;              /* skip one period */
  }
device_disappeared:
  {
    GST_ELEMENT_ERROR (asink, RESOURCE, WRITE,
        (_("Error outputting to audio device. "
                "The device has been disconnected.")), (NULL));
    goto write_error;
  }
}
示例#26
0
int main(int argc, char **argv)
{
   char *outFile;
   char *inFile[1];
// FILE *fout;
   FILE *fin[1];
   /*Holds the audio that will be written to file (16 bits per sample)*/
   short out[FRAME_SIZE];

    //int i;
    int result, length, tot_len;

    /*保存编码的状态*/         
    static void *stateDecode; 
   /*保存字节因此他们可以被speex常规读写*/
    static SpeexBits bitsDecode;
   //模式寄存器
    static const SpeexMode *mode=NULL;
   //解码器的采样频率
    static int speexFrequency = SAMPLERATE; //编码器的采样率
   /*得到的缓冲区的大小*/  
    static spx_int32_t frame_size; 
   /*得到的缓冲区的大小*/
   //static int channe = CHANNELS;
    /*得到是立体声*/
    //static SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; //单声到 立体声

   /* 初始话IP端口结构*/
#if (SAMPLERATE == 8000)
    mode = speex_lib_get_mode (SPEEX_MODEID_NB); //宽带编码
#elif (SAMPLERATE == 16000)
    mode = speex_lib_get_mode (SPEEX_MODEID_WB); //宽带编码
#elif (SAMPLERATE == 32000)
    mode = speex_lib_get_mode (SPEEX_MODEID_UWB); //宽带编码
#endif
    //mode = speex_lib_get_mode (SPEEX_MODEID_UWB); //在宽带模式解码


    stateDecode = speex_decoder_init(mode);      //新建一个解码器 

    speex_encoder_ctl(stateDecode, SPEEX_GET_FRAME_SIZE, &frame_size); //得到缓冲区大小

    speex_decoder_ctl(stateDecode, SPEEX_SET_SAMPLING_RATE, &speexFrequency); //设置解码器的采样频率

    speex_bits_init(&bitsDecode); //初始解码器

   char cbits[200];
   int nbBytes;
   /*Holds the state of the decoder*/
   //void *state;
   /*Holds bits so they can be read and written to by the Speex routines*/
   //SpeexBits bits;
   int i, tmp;
   int rc;

   printf("%s: start\n", __func__);


#if (SOUND_INTERFACE == SOUND_OSS)
	  init_oss_play();
#elif (SOUND_INTERFACE == SOUND_ALSA)
	 init_alsa_play();
#endif
   /*Create a new decoder state in narrowband mode*/
   stateDecode = speex_decoder_init(&speex_uwb_mode);

   /*Set the perceptual enhancement on*/
   tmp=1;
   speex_decoder_ctl(stateDecode, SPEEX_SET_ENH, &tmp);
   //printf("%s: 22222222\n", __func__);
	 inFile[0]	= argv[1];
	 //inFile[1]	= argv[2];	 
//   outFile = argv[1];
   //fout = fopen(outFile, "w");
   fin[0] = fopen(inFile[0], "r");//打开输入的spx文件
   
   if(fin[0] ==NULL)
   {
     perror("打开文件错误");
     exit(1);
   }
   
   //printf("%s: 3333333\n", __func__);
   /*Initialization of the structure that holds the bits*/
   speex_bits_init(&bitsDecode);
   //printf("%s: 4444444\n", __func__);   
   while (1)
   {   //printf("%s: 55555\n", __func__);
      //printf("%s: 1111111\n", __func__);
speex_bits_reset(&bitsDecode); 
      /*Read the size encoded by sampleenc, this part will likely be 
        different in your application*/
      fread(&nbBytes, sizeof(int), 1, fin[0]);
      fprintf (stderr, "nbBytes: %d\n", nbBytes);
      if (feof(fin[0]))
         break;
         //printf("%s: 666\n", __func__);
      /*Read the "packet" encoded by sampleenc*/
      fread(cbits, 1, nbBytes, fin[0]);
      /*Copy the data into the bit-stream struct*/
      speex_bits_read_from(&bitsDecode, cbits, nbBytes);

      /*Decode the data*/
      speex_decode_int(stateDecode, &bitsDecode, out);
#if 0
      /*Copy from float to short (16 bits) for output*/
      for (i=0;i<FRAME_SIZE;i++)
         out[i]=output[i];
   //printf("%s: 88888\n", __func__);
      /*Write the decoded audio to file*/
      //fwrite(out, sizeof(short), FRAME_SIZE, fout);
#endif 


#if (SOUND_INTERFACE == SOUND_OSS)
      rc = write(fdsoundplay, out, (SAMPLERATE/1000*READMSFORONCE)*sizeof(short));
      if(rc != (SAMPLERATE/1000*READMSFORONCE)*sizeof(short))
      {
          printf("写入数据长度与预期不符合\n");
      }
#elif (SOUND_INTERFACE == SOUND_ALSA)
      rc = snd_pcm_writei(handle, out, (SAMPLERATE/1000*READMSFORONCE)); 
         //printf("%s: 99999\n", __func__);

            if (rc == -EPIPE) 
            {
                /* EPIPE means underrun */
                fprintf(stderr, "underrun occurred\n");
                snd_pcm_prepare(handle);
            } 
            else if (rc < 0) 
            {
                fprintf(stderr, "error from writei: %s\n", snd_strerror(rc));
                        
                rc = xrun_recovery(handle, rc);             
                if (rc < 0) 
                {
                    printf("Write error: %s\n", snd_strerror(rc));
                    //return -1;
                }                   
            }  
            else if (rc != (int)(SAMPLERATE/1000*READMSFORONCE)) 
            {
                fprintf(stderr, "short write, write %d frames\n", rc);
            }
#endif
   }
   
printf("end\n");
   /*Destroy the decoder state*/
   speex_decoder_destroy(stateDecode);
   /*Destroy the bit-stream truct*/
   speex_bits_destroy(&bitsDecode);
   fclose(fin[0]);
   return 0;
}
示例#27
0
qint64 QAudioInputPrivate::read(char* data, qint64 len)
{
    // Read in some audio data and write it to QIODevice, pull mode
    if ( !handle )
        return 0;

    // bytesAvaiable is saved as a side effect of checkBytesReady().
    int bytesToRead = checkBytesReady();

    if (bytesToRead < 0) {
        // bytesAvailable as negative is error code, try to recover from it.
        xrun_recovery(bytesToRead);
        bytesToRead = checkBytesReady();
        if (bytesToRead < 0) {
            // recovery failed must stop and set error.
            close();
            errorState = QAudio::IOError;
            deviceState = QAudio::StoppedState;
            emit stateChanged(deviceState);
            return 0;
        }
    }

    bytesToRead = qMin<qint64>(len, bytesToRead);
    bytesToRead -= bytesToRead % period_size;
    int count=0, err = 0;
    while(count < 5) {
        int chunks = bytesToRead/period_size;
        int frames = chunks*period_frames;
        if(frames > (int)buffer_frames)
            frames = buffer_frames;
        int readFrames = snd_pcm_readi(handle, audioBuffer, frames);
        if (readFrames >= 0) {
            err = snd_pcm_frames_to_bytes(handle, readFrames);
#ifdef DEBUG_AUDIO
            qDebug()<<QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData();
#endif
            break;
        } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
            errorState = QAudio::IOError;
            err = 0;
            break;
        } else {
            if(readFrames == -EPIPE) {
                errorState = QAudio::UnderrunError;
                err = snd_pcm_prepare(handle);
            } else if(readFrames == -ESTRPIPE) {
                err = snd_pcm_prepare(handle);
            }
            if(err != 0) break;
        }
        count++;
    }
    if(err > 0) {
        // got some send it onward
#ifdef DEBUG_AUDIO
        qDebug()<<"frames to write to QIODevice = "<<
            snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes";
#endif
        if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
            return 0;
        if (pullMode) {
            qint64 l = audioSource->write(audioBuffer,err);
            if(l < 0) {
                close();
                errorState = QAudio::IOError;
                deviceState = QAudio::StoppedState;
                emit stateChanged(deviceState);
            } else if(l == 0) {
                if (deviceState != QAudio::IdleState) {
                    errorState = QAudio::NoError;
                    deviceState = QAudio::IdleState;
                    emit stateChanged(deviceState);
                }
            } else {
                bytesAvailable -= err;
                totalTimeValue += err;
                resuming = false;
                if (deviceState != QAudio::ActiveState) {
                    errorState = QAudio::NoError;
                    deviceState = QAudio::ActiveState;
                    emit stateChanged(deviceState);
                }
            }
            return l;

        } else {
            memcpy(data,audioBuffer,err);
            bytesAvailable -= err;
            totalTimeValue += err;
            resuming = false;
            if (deviceState != QAudio::ActiveState) {
                errorState = QAudio::NoError;
                deviceState = QAudio::ActiveState;
                emit stateChanged(deviceState);
            }
            return err;
        }
    }
    return 0;
}
示例#28
0
文件: alsa_out.c 项目: recri/keyer
/**
 * The process callback for this JACK application.
 * It is called by JACK at the appropriate times.
 */
int process (jack_nframes_t nframes, void *arg) {

    int rlen;
    int err;
    snd_pcm_sframes_t delay = target_delay;
    int i;

    delay = (num_periods*period_size)-snd_pcm_avail( alsa_handle ) ;

    delay -= jack_frames_since_cycle_start( client );
    // Do it the hard way.
    // this is for compensating xruns etc...

    if( delay > (target_delay+max_diff) ) {
	snd_pcm_rewind( alsa_handle, delay - target_delay );
	output_new_delay = (int) delay;

	delay = target_delay;

	// Set the resample_rate... we need to adjust the offset integral, to do this.
	// first look at the PI controller, this code is just a special case, which should never execute once
	// everything is swung in. 
	offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
	// Also clear the array. we are beginning a new control cycle.
	for( i=0; i<smooth_size; i++ )
		offset_array[i] = 0.0;
    }
    if( delay < (target_delay-max_diff) ) {

	output_new_delay = (int) delay;

	while ((target_delay-delay) > 0) {
	    snd_pcm_uframes_t to_write = ((target_delay-delay) > 512) ? 512 : (target_delay-delay);
	    snd_pcm_writei( alsa_handle, tmpbuf, to_write );
	    delay += to_write;
	}

	delay = target_delay;

	// Set the resample_rate... we need to adjust the offset integral, to do this.
	offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
	// Also clear the array. we are beginning a new control cycle.
	for( i=0; i<smooth_size; i++ )
		offset_array[i] = 0.0;
    }
    /* ok... now we should have target_delay +- max_diff on the alsa side.
     *
     * calculate the number of frames, we want to get.
     */

    double offset = delay - target_delay;

    // Save offset.
    offset_array[(offset_differential_index++)% smooth_size ] = offset;

    // Build the mean of the windowed offset array
    // basically fir lowpassing.
    double smooth_offset = 0.0;
    for( i=0; i<smooth_size; i++ )
	    smooth_offset +=
		    offset_array[ (i + offset_differential_index-1) % smooth_size] * window_array[i];
    smooth_offset /= (double) smooth_size;

    // this is the integral of the smoothed_offset
    offset_integral += smooth_offset;

    // Clamp offset.
    // the smooth offset still contains unwanted noise
    // which would go straigth onto the resample coeff.
    // it only used in the P component and the I component is used for the fine tuning anyways.
    if( fabs( smooth_offset ) < pclamp )
	    smooth_offset = 0.0;

    // ok. now this is the PI controller. 
    // u(t) = K * ( e(t) + 1/T \int e(t') dt' )
    // K = 1/catch_factor and T = catch_factor2
    double current_resample_factor = static_resample_factor - smooth_offset / (double) catch_factor - offset_integral / (double) catch_factor / (double)catch_factor2;

    // now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt.
    current_resample_factor = floor( (current_resample_factor - resample_mean) * controlquant + 0.5 ) / controlquant + resample_mean;

    // Output "instrumentatio" gonna change that to real instrumentation in a few.
    output_resampling_factor = (float) current_resample_factor;
    output_diff = (float) smooth_offset;
    output_integral = (float) offset_integral;
    output_offset = (float) offset;

    // Clamp a bit.
    if( current_resample_factor < resample_lower_limit ) current_resample_factor = resample_lower_limit;
    if( current_resample_factor > resample_upper_limit ) current_resample_factor = resample_upper_limit;

    // Now Calculate how many samples we need.
    rlen = ceil( ((double)nframes) * current_resample_factor )+2;
    assert( rlen > 2 );

    // Calculate resample_mean so we can init ourselves to saner values.
    resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
    /*
     * now this should do it...
     */

    outbuf = alloca( rlen * formats[format].sample_size * num_channels );

    resampbuf = alloca( rlen * sizeof( float ) );
    /*
     * render jack ports to the outbuf...
     */

    int chn = 0;
    JSList *node = playback_ports;
    JSList *src_node = playback_srcs;
    SRC_DATA src;

    while ( node != NULL)
    {
	jack_port_t *port = (jack_port_t *) node->data;
	float *buf = jack_port_get_buffer (port, nframes);

	SRC_STATE *src_state = src_node->data;

	src.data_in = buf;
	src.input_frames = nframes;

	src.data_out = resampbuf;
	src.output_frames = rlen;
	src.end_of_input = 0;

	src.src_ratio = current_resample_factor;

	src_process( src_state, &src );

	formats[format].jack_to_soundcard( outbuf + format[formats].sample_size * chn, resampbuf, src.output_frames_gen, num_channels*format[formats].sample_size, NULL);

	src_node = jack_slist_next (src_node);
	node = jack_slist_next (node);
	chn++;
    }

    // now write the output...
again:
  err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
  //err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
  if( err < 0 ) {
      printf( "err = %d\n", err );
      if (xrun_recovery(alsa_handle, err) < 0) {
	  printf("Write error: %s\n", snd_strerror(err));
	  exit(EXIT_FAILURE);
      }
      goto again;
  }

    return 0;      
}
示例#29
0
int alsamm_send_dacs(void)
{

  static double timenow,timelast;

  t_sample *fpo, *fpi, *fp1, *fp2;
  int i, err, devno;

  const snd_pcm_channel_area_t *my_areas;
  snd_pcm_sframes_t size;
  snd_pcm_sframes_t commitres;
  snd_pcm_state_t state;
  snd_pcm_sframes_t ooffset, oavail;
  snd_pcm_sframes_t ioffset, iavail;

  /*
     unused channels should be zeroed out on startup (open) and stay this
  */
  int inchannels = STUFF->st_inchannels;
  int outchannels = STUFF->st_outchannels;

  timelast = sys_getrealtime();

#ifdef ALSAMM_DEBUG
  if(dac_send++ < 0)
    post("dac send called in %d, out %d, xrun %d",inchannels,outchannels, alsamm_xruns);

  if(alsamm_xruns && (alsamm_xruns % 1000) == 0)
    post("1000 xruns accoured");

  if(dac_send < WATCH_PERIODS){
    out_cm[dac_send] = -1;
    in_avail[dac_send] = out_avail[dac_send] = -1;
    in_offset[dac_send] = out_offset[dac_send] = -1;
    outaddr[dac_send] = inaddr[dac_send] = NULL;
    xruns_watch[dac_send] = alsamm_xruns;
  }
#endif

  if (!inchannels && !outchannels)
    {
      return SENDDACS_NO;
    }

  /* here we should check if in and out samples are here.
     but, the point is if out samples available also in sample should,
     so we don't make a precheck of insamples here and let outsample check be the
     the first of the forst card.
  */


  /* OUTPUT Transfer */
  fpo = STUFF->st_soundout;
  for(devno = 0;devno < alsa_noutdev;devno++){

    t_alsa_dev *dev = &alsa_outdev[devno];
    snd_pcm_t *out = dev->a_handle;
    int ochannels =dev->a_channels;



    /* how much samples available ??? */
    oavail = snd_pcm_avail_update(out);

    /* only one reason i can think about,
       the driver stopped and says broken pipe
       so this should not happen if we have enough stopthreshhold
       but if try to restart with next commit
    */
    if (oavail < 0) {

#ifdef ALSAMM_DEBUG
      broken_opipe++;
#endif
      err = xrun_recovery(out, -EPIPE);
      if (err < 0) {
        check_error(err,"otavail<0 recovery failed");
        return SENDDACS_NO;
      }
      oavail = snd_pcm_avail_update(out);
    }

    /* check if we are late and have to (able to) catch up */
    /* xruns will be ignored since you cant do anything since already happened */
    state = snd_pcm_state(out);
    if (state == SND_PCM_STATE_XRUN) {
      err = xrun_recovery(out, -EPIPE);
      if (err < 0) {
        check_error(err,"DAC XRUN recovery failed");
        return SENDDACS_NO;
      }
      oavail = snd_pcm_avail_update(out);

    } else if (state == SND_PCM_STATE_SUSPENDED) {
      err = xrun_recovery(out, -ESTRPIPE);
      if (err < 0) {
        check_error(err,"DAC SUSPEND recovery failed");
        return SENDDACS_NO;
      }
      oavail = snd_pcm_avail_update(out);
    }

#ifdef ALSAMM_DEBUG
    if(dac_send < WATCH_PERIODS){
      out_avail[dac_send] = oavail;
    }
#endif

    /* we only transfer transfersize of bytes request,
       this should only happen on first card otherwise we got a problem :-(()*/

    if(oavail < alsamm_transfersize){
      return SENDDACS_NO;
    }

    /* transfer now */
    size = alsamm_transfersize;
    fp1 = fpo;
    ooffset = 0;

    /* since this can go over a buffer boundery we maybe need two steps to
       transfer (normally when buffersize is a multiple of transfersize
       this should never happen) */

    while (size > 0) {

      int chn;
      snd_pcm_sframes_t oframes;

      oframes = size;

      err =  alsamm_get_channels(out, (unsigned long *)&oframes,
        (unsigned long *)&ooffset,ochannels,dev->a_addr);

#ifdef ALSAMM_DEBUG
      if(dac_send < WATCH_PERIODS){
        out_offset[dac_send] = ooffset;
        outaddr[dac_send] = (char *) dev->a_addr[0];
      }
#endif

      if (err < 0){
        if ((err = xrun_recovery(out, err)) < 0) {
          check_error(err,"MMAP begins avail error");
          break; /* next card please */
        }
      }

      /* transfer into memory */
      for (chn = 0; chn < ochannels; chn++) {

        t_alsa_sample32 *buf = (t_alsa_sample32 *)dev->a_addr[chn];

        /*
        osc(buf, oframes, (dac_send%1000 < 500)?-100.0:-10.0,440,&(indexes[chn]));
        */

        for (i = 0, fp2 = fp1 + chn*alsamm_transfersize; i < oframes; i++,fp2++)
          {
            float s1 = *fp2 * F32MAX;
            /* better but slower, better never clip ;-)
               buf[i]= CLIP32(s1); */
            buf[i]= ((int) s1 & 0xFFFFFF00);
            *fp2 = 0.0;
          }
      }

      commitres = snd_pcm_mmap_commit(out, ooffset, oframes);
      if (commitres < 0 || commitres != oframes) {
        if ((err = xrun_recovery(out, commitres >= 0 ? -EPIPE : commitres)) < 0) {
          check_error(err,"MMAP commit error");
          return SENDDACS_NO;
        }
      }

#ifdef ALSAMM_DEBUG
      if(dac_send < WATCH_PERIODS)
        out_cm[dac_send] = oframes;
#endif

      fp1 += oframes;
      size -= oframes;
    } /* while size */
    fpo += ochannels*alsamm_transfersize;

  }/* for devno */


  fpi = STUFF->st_soundin; /* star first card first channel */

  for(devno = 0;devno < alsa_nindev;devno++){

    t_alsa_dev *dev = &alsa_indev[devno];
    snd_pcm_t *in = dev->a_handle;
    int ichannels = dev->a_channels;

    iavail = snd_pcm_avail_update(in);

    if (iavail < 0) {
      err = xrun_recovery(in, iavail);
      if (err < 0) {
        check_error(err,"input avail update failed");
        return SENDDACS_NO;
      }
      iavail=snd_pcm_avail_update(in);
    }

    state = snd_pcm_state(in);

    if (state == SND_PCM_STATE_XRUN) {
      err = xrun_recovery(in, -EPIPE);
      if (err < 0) {
        check_error(err,"ADC XRUN recovery failed");
        return SENDDACS_NO;
      }
      iavail=snd_pcm_avail_update(in);

    } else if (state == SND_PCM_STATE_SUSPENDED) {
      err = xrun_recovery(in, -ESTRPIPE);
      if (err < 0) {
        check_error(err,"ADC SUSPEND recovery failed");
        return SENDDACS_NO;
      }
      iavail=snd_pcm_avail_update(in);
    }

    /* only transfer full transfersize or nothing */
    if(iavail < alsamm_transfersize){
      return SENDDACS_NO;
    }
    size = alsamm_transfersize;
    fp1 = fpi;
    ioffset = 0;

    /* since sysdata can go over a driver buffer boundery we maybe need two steps to
       transfer (normally when buffersize is a multiple of transfersize
       this should never happen) */

    while(size > 0){
      int chn;
      snd_pcm_sframes_t iframes = size;

      err =  alsamm_get_channels(in,
        (unsigned long *)&iframes, (unsigned long *)&ioffset,ichannels,dev->a_addr);
      if (err < 0){
        if ((err = xrun_recovery(in, err)) < 0) {
          check_error(err,"MMAP begins avail error");
          return SENDDACS_NO;
        }
      }

#ifdef ALSAMM_DEBUG
      if(dac_send < WATCH_PERIODS){
        in_avail[dac_send] = iavail;
        in_offset[dac_send] = ioffset;
        inaddr[dac_send] = dev->a_addr[0];
      }
#endif
      /* transfer into memory */

      for (chn = 0; chn < ichannels; chn++) {

        t_alsa_sample32 *buf = (t_alsa_sample32 *) dev->a_addr[chn];

        for (i = 0, fp2 = fp1 + chn*alsamm_transfersize; i < iframes; i++,fp2++)
          {
            /* mask the lowest bits, since subchannels info can make zero samples nonzero */
            *fp2 = (float) ((t_alsa_sample32) (buf[i] & 0xFFFFFF00))
              * (1.0 / (float) INT32_MAX);
          }
      }

      commitres = snd_pcm_mmap_commit(in, ioffset, iframes);
      if (commitres < 0 || commitres != iframes) {
        post("please never");
        if ((err = xrun_recovery(in, commitres >= 0 ? -EPIPE : commitres)) < 0) {
          check_error(err,"MMAP synced in commit error");
          return SENDDACS_NO;
        }
      }
      fp1 += iframes;
      size -= iframes;
    }
    fpi += ichannels*alsamm_transfersize;
  } /* for out devno < alsamm_outcards*/


  if ((timenow = sys_getrealtime()) > (timelast + sleep_time))
    {

#ifdef ALSAMM_DEBUG
      if(dac_send < 10 && sys_verbose)
        post("slept %f > %f + %f (=%f)",
             timenow,timelast,sleep_time,(timelast + sleep_time));
#endif
      return (SENDDACS_SLEPT);
    }

  return SENDDACS_YES;
}
示例#30
0
qint64 QAlsaAudioInput::read(char* data, qint64 len)
{
    // Read in some audio data and write it to QIODevice, pull mode
    if ( !handle )
        return 0;

    int bytesRead = 0;
    int bytesInRingbufferBeforeRead = ringBuffer.bytesOfDataInBuffer();

    if (ringBuffer.bytesOfDataInBuffer() < len) {

        // bytesAvaiable is saved as a side effect of checkBytesReady().
        int bytesToRead = checkBytesReady();

        if (bytesToRead < 0) {
            // bytesAvailable as negative is error code, try to recover from it.
            xrun_recovery(bytesToRead);
            bytesToRead = checkBytesReady();
            if (bytesToRead < 0) {
                // recovery failed must stop and set error.
                close();
                errorState = QAudio::IOError;
                deviceState = QAudio::StoppedState;
                emit stateChanged(deviceState);
                return 0;
            }
        }

        bytesToRead = qMin<qint64>(len, bytesToRead);
        bytesToRead = qMin<qint64>(ringBuffer.freeBytes(), bytesToRead);
        bytesToRead -= bytesToRead % period_size;

        int count=0;
        int err = 0;
        while(count < 5 && bytesToRead > 0) {
            char buffer[bytesToRead];
            int chunks = bytesToRead / period_size;
            int frames = chunks * period_frames;
            if (frames > (int)buffer_frames)
                frames = buffer_frames;

            int readFrames = snd_pcm_readi(handle, buffer, frames);
            bytesRead = snd_pcm_frames_to_bytes(handle, readFrames);
            if (m_volume < 1.0f)
                QAudioHelperInternal::qMultiplySamples(m_volume, settings, buffer, buffer, bytesRead);

            if (readFrames >= 0) {
                ringBuffer.write(buffer, bytesRead);
#ifdef DEBUG_AUDIO
                qDebug() << QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(bytesRead).arg(readFrames).toLatin1().constData();
#endif
                break;
            } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
                errorState = QAudio::IOError;
                err = 0;
                break;
            } else {
                if(readFrames == -EPIPE) {
                    errorState = QAudio::UnderrunError;
                    err = snd_pcm_prepare(handle);
                } else if(readFrames == -ESTRPIPE) {
                    err = snd_pcm_prepare(handle);
                }
                if(err != 0) break;
            }
            count++;
        }

    }

    bytesRead += bytesInRingbufferBeforeRead;

    if (bytesRead > 0) {
        // got some send it onward
#ifdef DEBUG_AUDIO
        qDebug() << "frames to write to QIODevice = " <<
            snd_pcm_bytes_to_frames( handle, (int)bytesRead ) << " (" << bytesRead << ") bytes";
#endif
        if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
            return 0;

        if (pullMode) {
            qint64 l = 0;
            qint64 bytesWritten = 0;
            while (ringBuffer.bytesOfDataInBuffer() > 0) {
                l = audioSource->write(ringBuffer.availableData(), ringBuffer.availableDataBlockSize());
                if (l > 0) {
                    ringBuffer.readBytes(l);
                    bytesWritten += l;
                } else {
                    break;
                }
            }

            if (l < 0) {
                close();
                errorState = QAudio::IOError;
                deviceState = QAudio::StoppedState;
                emit stateChanged(deviceState);
            } else if (l == 0 && bytesWritten == 0) {
                if (deviceState != QAudio::IdleState) {
                    errorState = QAudio::NoError;
                    deviceState = QAudio::IdleState;
                    emit stateChanged(deviceState);
                }
            } else {
                bytesAvailable -= bytesWritten;
                totalTimeValue += bytesWritten;
                resuming = false;
                if (deviceState != QAudio::ActiveState) {
                    errorState = QAudio::NoError;
                    deviceState = QAudio::ActiveState;
                    emit stateChanged(deviceState);
                }
            }

            return bytesWritten;
        } else {
            while (ringBuffer.bytesOfDataInBuffer() > 0) {
                int size = ringBuffer.availableDataBlockSize();
                memcpy(data, ringBuffer.availableData(), size);
                data += size;
                ringBuffer.readBytes(size);
            }

            bytesAvailable -= bytesRead;
            totalTimeValue += bytesRead;
            resuming = false;
            if (deviceState != QAudio::ActiveState) {
                errorState = QAudio::NoError;
                deviceState = QAudio::ActiveState;
                emit stateChanged(deviceState);
            }

            return bytesRead;
        }
    }

    return 0;
}