diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-03-19 00:48:43 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-03-19 00:48:43 +0000 |
commit | 431b82df08e0061f6676122c731d40915fb747df (patch) | |
tree | a33965163cd3f5d2b84655feeaf3b48cb1dd1ebb | |
parent | 4d6e1b4cf1cbdec88bd4c4915fb27a16ee89acb4 (diff) |
Tested and fixed stereo audio support
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@334 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r-- | pjmedia/include/pjmedia/errno.h | 26 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/errno.c | 6 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/file_port.c | 13 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/pasound.c | 36 |
4 files changed, 65 insertions, 16 deletions
diff --git a/pjmedia/include/pjmedia/errno.h b/pjmedia/include/pjmedia/errno.h index 3d95c44a..67c4d011 100644 --- a/pjmedia/include/pjmedia/errno.h +++ b/pjmedia/include/pjmedia/errno.h @@ -442,6 +442,32 @@ PJ_BEGIN_DECL #define PJMEDIA_EWAVETOOSHORT (PJMEDIA_ERRNO_START+182) /* 220182 */ +/************************************************************ + * SOUND DEVICE ERRORS + ***********************************************************/ +/** + * @hideinitializer + * No suitable audio capture device. + */ +#define PJMEDIA_ENOSNDREC (PJMEDIA_ERRNO_START+200) /* 220200 */ +/** + * @hideinitializer + * No suitable audio playback device. + */ +#define PJMEDIA_ENOSNDPLAY (PJMEDIA_ERRNO_START+201) /* 220201 */ +/** + * @hideinitializer + * Invalid sound device ID. + */ +#define PJMEDIA_ESNDINDEVID (PJMEDIA_ERRNO_START+202) /* 220202 */ +/** + * @hideinitializer + * Invalid sample format for sound device. + */ +#define PJMEDIA_ESNDINSAMPLEFMT (PJMEDIA_ERRNO_START+203) /* 220203 */ + + + PJ_END_DECL #endif /* __PJMEDIA_ERRNO_H__ */ diff --git a/pjmedia/src/pjmedia/errno.c b/pjmedia/src/pjmedia/errno.c index 5a63e07e..7ea7af8c 100644 --- a/pjmedia/src/pjmedia/errno.c +++ b/pjmedia/src/pjmedia/errno.c @@ -122,6 +122,12 @@ static const struct { PJMEDIA_ENOTVALIDWAVE, "Not a valid WAVE file" }, { PJMEDIA_EWAVEUNSUPP, "Unsupported WAVE file format" }, { PJMEDIA_EWAVETOOSHORT, "WAVE file too short" }, + + /* Sound device errors: */ + { PJMEDIA_ENOSNDREC, "No suitable sound capture device" }, + { PJMEDIA_ENOSNDPLAY, "No suitable sound playback device" }, + { PJMEDIA_ESNDINDEVID, "Invalid sound device ID" }, + { PJMEDIA_ESNDINSAMPLEFMT, "Invalid sample format for sound device" }, }; #endif /* PJ_HAS_ERROR_STRING */ diff --git a/pjmedia/src/pjmedia/file_port.c b/pjmedia/src/pjmedia/file_port.c index 573637be..11e59eec 100644 --- a/pjmedia/src/pjmedia/file_port.c +++ b/pjmedia/src/pjmedia/file_port.c @@ -199,14 +199,20 @@ PJ_DEF(pj_status_t) pjmedia_file_player_port_create( pj_pool_t *pool, return PJMEDIA_ENOTVALIDWAVE; } + /* Must be PCM with 16bits per sample */ if (wave_hdr.fmt_hdr.fmt_tag != 1 || - wave_hdr.fmt_hdr.bits_per_sample != 16 || - wave_hdr.fmt_hdr.block_align != 2) + wave_hdr.fmt_hdr.bits_per_sample != 16) { pj_file_close(fport->fd); return PJMEDIA_EWAVEUNSUPP; } + /* Block align must be 2*nchannels */ + if (wave_hdr.fmt_hdr.block_align != wave_hdr.fmt_hdr.nchan*2) { + pj_file_close(fport->fd); + return PJMEDIA_EWAVEUNSUPP; + } + /* Validate length. */ if (wave_hdr.data_hdr.len != fport->fsize-sizeof(pjmedia_wave_hdr)) { pj_file_close(fport->fd); @@ -227,7 +233,8 @@ PJ_DEF(pj_status_t) pjmedia_file_player_port_create( pj_pool_t *pool, fport->base.info.sample_rate = wave_hdr.fmt_hdr.sample_rate; fport->base.info.bits_per_sample = wave_hdr.fmt_hdr.bits_per_sample; fport->base.info.samples_per_frame = fport->base.info.sample_rate * - 20 / 1000; + wave_hdr.fmt_hdr.nchan * + 20 / 1000; fport->base.info.bytes_per_frame = fport->base.info.samples_per_frame * fport->base.info.bits_per_sample / 8; diff --git a/pjmedia/src/pjmedia/pasound.c b/pjmedia/src/pjmedia/pasound.c index ffac434c..cb36b927 100644 --- a/pjmedia/src/pjmedia/pasound.c +++ b/pjmedia/src/pjmedia/pasound.c @@ -85,7 +85,8 @@ static int PaRecorderCallback(const void *input, stream->timestamp += frameCount; status = (*stream->rec_cb)(stream->user_data, stream->timestamp, - input, frameCount * stream->bytes_per_sample); + input, frameCount * stream->bytes_per_sample * + stream->channel_count); if (status==0) return paContinue; @@ -104,7 +105,8 @@ static int PaPlayerCallback( const void *input, { pjmedia_snd_stream *stream = userData; pj_status_t status; - unsigned size = frameCount * stream->bytes_per_sample; + unsigned size = frameCount * stream->bytes_per_sample * + stream->channel_count; PJ_UNUSED_ARG(input); PJ_UNUSED_ARG(timeInfo); @@ -206,6 +208,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, PaStreamParameters inputParam; int sampleFormat; const PaDeviceInfo *paDevInfo = NULL; + unsigned paFrames; PaError err; if (index == -1) { @@ -217,13 +220,13 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, } if (index == count) { /* No such device. */ - return PJ_ENOTFOUND; + return PJMEDIA_ENOSNDREC; } } else { paDevInfo = Pa_GetDeviceInfo(index); if (!paDevInfo) { /* Assumed it is "No such device" error. */ - return PJ_ENOTFOUND; + return PJMEDIA_ESNDINDEVID; } } @@ -234,7 +237,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, else if (bits_per_sample == 32) sampleFormat = paInt32; else - return PJ_ENOTSUP; + return PJMEDIA_ESNDINSAMPLEFMT; pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL); if (!pool) @@ -257,9 +260,12 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, inputParam.sampleFormat = sampleFormat; inputParam.suggestedLatency = paDevInfo->defaultLowInputLatency; + /* Frames in PortAudio is number of samples in a single channel */ + paFrames = samples_per_frame / channel_count; + err = Pa_OpenStream( &stream->stream, &inputParam, NULL, - clock_rate, samples_per_frame, - 0, &PaRecorderCallback, stream ); + clock_rate, paFrames, + paClipOff, &PaRecorderCallback, stream ); if (err != paNoError) { pj_pool_release(pool); return PJMEDIA_ERRNO_FROM_PORTAUDIO(err); @@ -291,6 +297,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index, PaStreamParameters outputParam; int sampleFormat; const PaDeviceInfo *paDevInfo = NULL; + unsigned paFrames; PaError err; if (index == -1) { @@ -302,13 +309,13 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index, } if (index == count) { /* No such device. */ - return PJ_ENOTFOUND; + return PJMEDIA_ENOSNDPLAY; } } else { paDevInfo = Pa_GetDeviceInfo(index); if (!paDevInfo) { /* Assumed it is "No such device" error. */ - return PJ_ENOTFOUND; + return PJMEDIA_ESNDINDEVID; } } @@ -319,7 +326,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index, else if (bits_per_sample == 32) sampleFormat = paInt32; else - return PJ_ENOTSUP; + return PJMEDIA_ESNDINSAMPLEFMT; pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL); if (!pool) @@ -342,9 +349,12 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index, outputParam.sampleFormat = sampleFormat; outputParam.suggestedLatency = paDevInfo->defaultLowInputLatency; + /* Frames in PortAudio is number of samples in a single channel */ + paFrames = samples_per_frame / channel_count; + err = Pa_OpenStream( &stream->stream, NULL, &outputParam, - clock_rate, samples_per_frame, - 0, &PaPlayerCallback, stream ); + clock_rate, paFrames, + paClipOff, &PaPlayerCallback, stream ); if (err != paNoError) { pj_pool_release(pool); return PJMEDIA_ERRNO_FROM_PORTAUDIO(err); @@ -352,7 +362,7 @@ PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index, PJ_LOG(5,(THIS_FILE, "%s opening device %s for playing, sample rate=%d, " "channel count=%d, " - "%d bits per sample, %d samples per buffer", + "%d bits per sample, %d samples per frame", (err==0 ? "Success" : "Error"), paDevInfo->name, clock_rate, channel_count, bits_per_sample, samples_per_frame)); |