diff options
| author | Bent Bisballe Nyeng <deva@aasimon.org> | 2012-08-02 20:43:30 +0200 | 
|---|---|---|
| committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2012-08-02 20:43:30 +0200 | 
| commit | 90fb73a91936ede98ccedda073929397ddf842b1 (patch) | |
| tree | c83b8f8ebdfdea527f01b6afede8f90d03bd0fa4 /src | |
| parent | f83b395168155d0421dbc093a37bd075dc51ed53 (diff) | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 6 | ||||
| -rw-r--r-- | src/audio.cc | 214 | ||||
| -rw-r--r-- | src/audio.h | 1 | ||||
| -rw-r--r-- | src/audioin.cc | 17 | ||||
| -rw-r--r-- | src/audioout.cc | 7 | ||||
| -rw-r--r-- | src/crosscomposer.cc | 18 | 
6 files changed, 251 insertions, 12 deletions
| diff --git a/src/Makefile.am b/src/Makefile.am index db3a5b5..a57457a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,16 +2,18 @@ SUBDIRS =  bin_PROGRAMS = crosscomposer -crosscomposer_LDADD = $(ALSA_LIBS) $(AO_LIBS) -crosscomposer_CXXFLAGS = $(ALSA_CFLAGS) $(AO_CFLAGS) +crosscomposer_LDADD = $(PA_LIBS) $(ALSA_LIBS) $(AO_LIBS) +crosscomposer_CXXFLAGS = $(PA_CFLAGS) $(ALSA_CFLAGS) $(AO_CFLAGS)  crosscomposer_SOURCES = \  	crosscomposer.cc \ +	audio.cc \  	audioin.cc \  	audioout.cc \  	socket.cc  EXTRA_DIST = \ +	audio.h \  	audioin.h \  	audioout.h \  	socket.h diff --git a/src/audio.cc b/src/audio.cc new file mode 100644 index 0000000..ffe65c2 --- /dev/null +++ b/src/audio.cc @@ -0,0 +1,214 @@ +/* + * $Id: patest_read_record.c 757 2004-02-13 07:48:10Z rossbencina $ + * + * This program uses the PortAudio Portable Audio Library. + * For more information see: http://www.portaudio.com + * Copyright (c) 1999-2000 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * The text above constitutes the entire PortAudio license; however,  + * the PortAudio community also makes the following non-binding requests: + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. It is also  + * requested that these non-binding requests be included along with the  + * license above. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <portaudio.h> + +/* #define SAMPLE_RATE  (17932) // Test failure to open with this value. */ +#define SAMPLE_RATE  (44100) +#define FRAMES_PER_BUFFER (32) +#define NUM_CHANNELS    (1) +#define NUM_SECONDS     (15) +/* #define DITHER_FLAG     (paDitherOff)  */ +#define DITHER_FLAG     (0)  + +/* @todo Underflow and overflow is disabled until we fix priming of blocking write. */ +#define CHECK_OVERFLOW  (0) +#define CHECK_UNDERFLOW  (0) + + +/* Select sample format. */ +#if 1 +#define PA_SAMPLE_TYPE  paFloat32 +#define SAMPLE_SIZE (4) +#define SAMPLE_SILENCE  (0.0f) +#define CLEAR(a) memset( (a), 0, FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ) +#define PRINTF_S_FORMAT "%.8f" +#elif 0 +#define PA_SAMPLE_TYPE  paInt16 +#define SAMPLE_SIZE (2) +#define SAMPLE_SILENCE  (0) +#define CLEAR(a) memset( (a), 0,  FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ) +#define PRINTF_S_FORMAT "%d" +#elif 0 +#define PA_SAMPLE_TYPE  paInt24 +#define SAMPLE_SIZE (3) +#define SAMPLE_SILENCE  (0) +#define CLEAR(a) memset( (a), 0,  FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ) +#define PRINTF_S_FORMAT "%d" +#elif 0 +#define PA_SAMPLE_TYPE  paInt8 +#define SAMPLE_SIZE (1) +#define SAMPLE_SILENCE  (0) +#define CLEAR(a) memset( (a), 0,  FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ) +#define PRINTF_S_FORMAT "%d" +#else +#define PA_SAMPLE_TYPE  paUInt8 +#define SAMPLE_SIZE (1) +#define SAMPLE_SILENCE  (128) +#define CLEAR( a ) { \ +    int i; \ +    for( i=0; i<FRAMES_PER_BUFFER*NUM_CHANNELS; i++ ) \ +        ((unsigned char *)a)[i] = (SAMPLE_SILENCE); \ +} +#define PRINTF_S_FORMAT "%d" +#endif + + +/*******************************************************************/ +int pamain(void) +{ +    PaStreamParameters inputParameters, outputParameters; +    PaStream *stream = NULL; +    PaError err; +    char *sampleBlock; +    int i; +    int numBytes; +     +     +    printf("patest_read_write_wire.c\n"); fflush(stdout); + +    numBytes = FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE ; +    sampleBlock = (char *) malloc( numBytes ); +    if( sampleBlock == NULL ) +    { +        printf("Could not allocate record array.\n"); +        exit(1); +    } +    CLEAR( sampleBlock ); + +    err = Pa_Initialize(); +    if( err != paNoError ) goto error; + +    inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */ +    printf( "Input device # %d.\n", inputParameters.device ); +    printf( "Input LL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency ); +    printf( "Input HL: %g s\n", Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ); +    inputParameters.channelCount = NUM_CHANNELS; +    inputParameters.sampleFormat = PA_SAMPLE_TYPE; +    inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ; +    inputParameters.hostApiSpecificStreamInfo = NULL; + +    outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ +    printf( "Output device # %d.\n", outputParameters.device ); +    printf( "Output LL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency ); +    printf( "Output HL: %g s\n", Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency ); +    outputParameters.channelCount = NUM_CHANNELS; +    outputParameters.sampleFormat = PA_SAMPLE_TYPE; +    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; +    outputParameters.hostApiSpecificStreamInfo = NULL; + +    /* -- setup -- */ + +   err = Pa_OpenStream( +              &stream, +              &inputParameters, +              &outputParameters, +              SAMPLE_RATE, +              FRAMES_PER_BUFFER, +              paClipOff,      /* we won't output out of range samples so don't bother clipping them */ +              NULL, /* no callback, use blocking API */ +              NULL ); /* no callback, so no callback userData */ +    if( err != paNoError ) goto error; + +    err = Pa_StartStream( stream ); +    if( err != paNoError ) goto error; +    printf("Wire on. Will run %d seconds.\n", NUM_SECONDS); fflush(stdout); + +    for( i=0; i<(NUM_SECONDS*SAMPLE_RATE)/FRAMES_PER_BUFFER; ++i ) +    { +       err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER ); +       if( err && CHECK_OVERFLOW ) goto xrun; +       err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER ); +       if( err && CHECK_UNDERFLOW ) goto xrun; +    } +    err = Pa_StopStream( stream ); +    if( err != paNoError ) goto error; + +    CLEAR( sampleBlock ); +/* +    err = Pa_StartStream( stream ); +    if( err != paNoError ) goto error; +    printf("Wire on. Interrupt to stop.\n"); fflush(stdout); + +    while( 1 ) +    { +       err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER ); +       if( err ) goto xrun; +       err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER ); +       if( err ) goto xrun; +    } +    err = Pa_StopStream( stream ); +    if( err != paNoError ) goto error; + +    Pa_CloseStream( stream ); +*/ +    free( sampleBlock ); + +    Pa_Terminate(); +    return 0; + +xrun: +    if( stream ) { +       Pa_AbortStream( stream ); +       Pa_CloseStream( stream ); +    } +    free( sampleBlock ); +    Pa_Terminate(); +    if( err & paInputOverflow ) +       fprintf( stderr, "Input Overflow.\n" ); +    if( err & paOutputUnderflow ) +       fprintf( stderr, "Output Underflow.\n" ); +    return -2; + +error: +    if( stream ) { +       Pa_AbortStream( stream ); +       Pa_CloseStream( stream ); +    } +    free( sampleBlock ); +    Pa_Terminate(); +    fprintf( stderr, "An error occured while using the portaudio stream\n" ); +    fprintf( stderr, "Error number: %d\n", err ); +    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); +    return -1; +} + + diff --git a/src/audio.h b/src/audio.h new file mode 100644 index 0000000..bf2370c --- /dev/null +++ b/src/audio.h @@ -0,0 +1 @@ +int pamain(); diff --git a/src/audioin.cc b/src/audioin.cc index 3792ae2..b15666f 100644 --- a/src/audioin.cc +++ b/src/audioin.cc @@ -29,6 +29,7 @@  AudioIn::AudioIn(std::string device, std::string mixer_interface,                   unsigned int srate, int ch)  { +  /*    frames = 940;    elem = NULL; @@ -78,6 +79,7 @@ AudioIn::AudioIn(std::string device, std::string mixer_interface,    if (rc < 0) throw UnableToSetHWParams();    mixhnd = NULL; +  */    /*    //    // Set up mixer @@ -138,8 +140,20 @@ AudioIn::~AudioIn()    if(mixhnd) snd_mixer_close(mixhnd);  } +#define TEST +#ifdef TEST +#include <math.h> +#endif/*TEST*/  size_t AudioIn::read(sample_t *buf, size_t size)  { +#ifdef TEST +  static unsigned int x = 0; +  for(size_t i = 0; i < size; i++) { +    buf[i] = sin((float)x / 50.0); +    x++; +  } +  return size; +#else  	int rc;  	if(size < frames * channels) { @@ -157,8 +171,9 @@ size_t AudioIn::read(sample_t *buf, size_t size)  	} else if (rc != (int)frames) {      throw ShortRead();  	} - +  printf("rc: %d\n", rc);  	return rc * channels; +#endif/*TEST*/  }  int AudioIn::set_level(unsigned int channel, float level) diff --git a/src/audioout.cc b/src/audioout.cc index 0495a2c..b0ab3d7 100644 --- a/src/audioout.cc +++ b/src/audioout.cc @@ -29,8 +29,6 @@  #define T(x, msg) if(x < 0) { printf("%s failed: %s\n", msg, snd_strerror(x)); fflush(stdout); } -#define BUFSZ 40960 -  AudioOut::AudioOut(std::string device, unsigned int srate, int channels)  {    handle = NULL; @@ -83,5 +81,8 @@ AudioOut::~AudioOut()  void AudioOut::write(sample_t *samples, size_t size)  {    // Write the interleaved buffer to the soundcard -  snd_pcm_writei(handle, samples, size); +  size_t sz = 0; +  while(size > sz) { +    sz += snd_pcm_writei(handle, samples + sz, size - sz); +  }  } diff --git a/src/crosscomposer.cc b/src/crosscomposer.cc index 010aa92..169fd4c 100644 --- a/src/crosscomposer.cc +++ b/src/crosscomposer.cc @@ -32,13 +32,19 @@  #include "audioin.h"  #include "audioout.h" +#include "audio.h" +  #define NUM_SAMPLES 940  int main(int argc, char *argv[])  { -  sample_t samples[940]; +  sample_t samples[NUM_SAMPLES];    Socket s;    s.open("127.0.0.1", 10000); +  int loop = 100; + +  return pamain(); +    switch(fork()) {    case 0: @@ -46,11 +52,11 @@ int main(int argc, char *argv[])        AudioIn in("default", "Capture", 44100, 1);        s.setSend(0); -      int i = 50; -      while(i--) { +      while(loop--) {          int sz = in.read(samples, NUM_SAMPLES);          for(size_t i = 0; i < NUM_SAMPLES; i++) { -          samples[i] = ((sample_t)rand() / (float)RAND_MAX) * 10; +          //samples[i] = ((sample_t)rand() / (float)RAND_MAX) * 10; +          //samples[i] *= 30;          }          s.sendTo(samples, sz * sizeof(sample_t));          printf("s"); fflush(stdout); @@ -64,10 +70,10 @@ int main(int argc, char *argv[])        s.setRecv();        AudioOut out("default", 44100, 1); -      int i = 50; -      while(i--) { +      while(loop--) {          int sz = s.recvFrom(samples, sizeof(samples));          out.write(samples, sz / sizeof(sample_t)); +        sz = sz;          printf("r%f", samples[0]); fflush(stdout);        }        printf("R!\n"); | 
