Index: pjproject/trunk/pjmedia/include/pjmedia/errno.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 333)
+++ pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 334)
@@ -443,4 +443,30 @@
 
 
+/************************************************************
+ * 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
 
Index: pjproject/trunk/pjmedia/src/pjmedia/errno.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 333)
+++ pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 334)
@@ -123,4 +123,10 @@
     { 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" },
 };
 
Index: pjproject/trunk/pjmedia/src/pjmedia/file_port.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/file_port.c	(revision 333)
+++ pjproject/trunk/pjmedia/src/pjmedia/file_port.c	(revision 334)
@@ -200,8 +200,14 @@
     }
 
+    /* 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;
@@ -228,5 +234,6 @@
     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 * 
Index: pjproject/trunk/pjmedia/src/pjmedia/pasound.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 333)
+++ pjproject/trunk/pjmedia/src/pjmedia/pasound.c	(revision 334)
@@ -86,5 +86,6 @@
 
     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) 
@@ -105,5 +106,6 @@
     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);
@@ -207,4 +209,5 @@
     int sampleFormat;
     const PaDeviceInfo *paDevInfo = NULL;
+    unsigned paFrames;
     PaError err;
 
@@ -218,5 +221,5 @@
 	if (index == count) {
 	    /* No such device. */
-	    return PJ_ENOTFOUND;
+	    return PJMEDIA_ENOSNDREC;
 	}
     } else {
@@ -224,5 +227,5 @@
 	if (!paDevInfo) {
 	    /* Assumed it is "No such device" error. */
-	    return PJ_ENOTFOUND;
+	    return PJMEDIA_ESNDINDEVID;
 	}
     }
@@ -235,5 +238,5 @@
 	sampleFormat = paInt32;
     else
-	return PJ_ENOTSUP;
+	return PJMEDIA_ESNDINSAMPLEFMT;
     
     pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);
@@ -258,7 +261,10 @@
     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);
@@ -292,4 +298,5 @@
     int sampleFormat;
     const PaDeviceInfo *paDevInfo = NULL;
+    unsigned paFrames;
     PaError err;
 
@@ -303,5 +310,5 @@
 	if (index == count) {
 	    /* No such device. */
-	    return PJ_ENOTFOUND;
+	    return PJMEDIA_ENOSNDPLAY;
 	}
     } else {
@@ -309,5 +316,5 @@
 	if (!paDevInfo) {
 	    /* Assumed it is "No such device" error. */
-	    return PJ_ENOTFOUND;
+	    return PJMEDIA_ESNDINDEVID;
 	}
     }
@@ -320,5 +327,5 @@
 	sampleFormat = paInt32;
     else
-	return PJ_ENOTSUP;
+	return PJMEDIA_ESNDINSAMPLEFMT;
     
     pool = pj_pool_create( snd_mgr.factory, "sndstream", 1024, 1024, NULL);
@@ -343,7 +350,10 @@
     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);
@@ -353,5 +363,5 @@
     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,
