--- a/src/sc2mpd.cpp
+++ b/src/sc2mpd.cpp
@@ -20,6 +20,8 @@
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Modified from ohSongcast/Receiver/Receiver.cpp
*/
#include "config.h"
@@ -37,10 +39,16 @@
#include "rcvqueue.h"
#include "log.h"
#include "conftree.h"
+#include "chrono.h"
#include <vector>
#include <stdio.h>
#include <iostream>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
using namespace std;
WorkQueue<AudioMessage*> audioqueue("audioqueue", 2);
@@ -50,8 +58,6 @@
#pragma warning(disable:4355) // use of 'this' in ctor lists safe in this case
#define CDECL __cdecl
-
-#include <conio.h>
int mygetch()
{
@@ -107,16 +113,35 @@
virtual void Process(OhmMsgMetatext& aMsg);
private:
- TBool iReset;
- TUint iCount;
- TUint iFrame;
+ // Debug, stats, etc while we get to understand the Songcast streams
+ class Observer {
+ public:
+ TBool iReset;
+ TUint iCount;
+ TUint iFrame;
+ int dumpfd;
+ Chrono chron;
+ Observer() : iReset(true), iCount(0), iFrame(0), dumpfd(-1) {
+#if 0
+ dumpfd =
+ open("/y/av/tmp/sc2dump", O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ if (dumpfd < 0) {
+ LOGERR("OhmReceiverDriver::Open dump file failed\n");
+ }
+#endif
+ }
+
+ void reset() {
+ iReset = true;
+ }
+
+ void process(OhmMsgAudio& aMsg);
+ };
+ Observer obs;
};
-
OhmReceiverDriver::OhmReceiverDriver(int port)
{
- iReset = true;
- iCount = 0;
AudioEaterContext *ctxt = new AudioEaterContext(port);
audioqueue.start(1, &audioEater, ctxt);
}
@@ -138,7 +163,7 @@
void OhmReceiverDriver::Connected()
{
- iReset = true;
+ obs.reset();
LOGDEB("=== CONNECTED ====\n");
}
@@ -159,13 +184,59 @@
LOGDEB("=== STOPPED ====\n");
}
-void OhmReceiverDriver::Process(OhmMsgAudio& aMsg)
+void OhmReceiverDriver::Observer::process(OhmMsgAudio& aMsg)
{
if (++iCount == 400 || aMsg.Halt()) {
+ static unsigned long long last_timestamp;
+ unsigned long long timestamp = aMsg.MediaTimestamp();
LOGDEB("OhmRcvDrv::Process:audio: samplerate " << aMsg.SampleRate() <<
" bitdepth " << aMsg.BitDepth() << " channels " <<
aMsg.Channels() << " samples " << aMsg.Samples() <<
" Halted ? " << aMsg.Halt() << endl);
+
+ if (last_timestamp) {
+ long long intervalus =
+ ((timestamp - last_timestamp) * 1000000) / (256*48000);
+ long long atsus =
+ ((timestamp) * 1000000) / (256*48000);
+ long long absus = chron.amicros() - 1430477861905884LL;
+ LOGDEB("Computed-uS: " << intervalus <<
+ " Elapsed-uS: " << chron.urestart() <<
+ " Timestamp-uS: " << atsus <<
+ " Abs-uS: " << absus <<
+ " Diff-mS " << (absus - atsus) / 1000 <<
+ endl);
+ }
+ last_timestamp = timestamp;
+
+ if (!aMsg.Halt()) {
+ unsigned int bytes =
+ aMsg.Samples() * (aMsg.BitDepth() / 8) * aMsg.Channels();
+
+ if (bytes != aMsg.Audio().Bytes()) {
+ LOGERR("OhmRcvDrv::Process:audio: computed bytes " << bytes <<
+ " != bufer's " << aMsg.Audio().Bytes() << endl);
+ bytes = aMsg.Audio().Bytes();
+ }
+ const unsigned char *icp =
+ (const unsigned char *)aMsg.Audio().Ptr();
+ bool silence = true;
+ for (unsigned int i = 0; i < bytes; i++) {
+ if (icp[i]) {
+ silence = false;
+ break;
+ }
+ }
+ if (silence) {
+ LOGDEB("OhmRcvDrv::Process:audio: silence buffer" << endl);
+ }
+ if (dumpfd >= 0) {
+ if (write(dumpfd, icp, bytes) != int(bytes)) {
+ ;
+ }
+ }
+ }
+
iCount = 0;
}
@@ -179,20 +250,27 @@
}
iFrame = aMsg.Frame();
}
-
- if (aMsg.Audio().Bytes() == 0)
+}
+
+void OhmReceiverDriver::Process(OhmMsgAudio& aMsg)
+{
+
+ if (aMsg.Audio().Bytes() == 0) {
+ LOGDEB("OhmReceiverDriver::Process: empty message\n");
return;
-
- unsigned int bytes =
- aMsg.Samples() * (aMsg.BitDepth() / 8) * aMsg.Channels();
-
- if (bytes != aMsg.Audio().Bytes()) {
- LOGERR("OhmRcvDrv::Process:audio: computed bytes " << bytes <<
- " != bufer's " << aMsg.Audio().Bytes() << endl);
- bytes = aMsg.Audio().Bytes();
- }
-
+ }
+
+ unsigned int bytes = aMsg.Audio().Bytes();
char *buf = (char *)malloc(bytes);
+ if (buf == 0) {
+ LOGERR("OhmReceiverDriver::Process: can't allocate " <<
+ bytes << " bytes\n");
+ return;
+ }
+
+#ifdef WORDS_BIGENDIAN
+ memcpy(buf, aMsg.Audio().Ptr(), bytes);
+#else
if (aMsg.BitDepth() == 16) {
swab(aMsg.Audio().Ptr(), buf, bytes);
} else if (aMsg.BitDepth() == 24) {
@@ -206,7 +284,19 @@
icp += 3;
}
} else if (aMsg.BitDepth() == 32) {
- }
+ // Never seen this but whatever...
+ unsigned char *ocp = (unsigned char *)buf;
+ const unsigned char *icp = (const unsigned char *)aMsg.Audio().Ptr();
+ const unsigned char *icp0 = icp;
+ while (icp - icp0 <= int(bytes) - 4) {
+ *ocp++ = icp[3];
+ *ocp++ = icp[2];
+ *ocp++ = icp[1];
+ *ocp++ = *icp;
+ icp += 4;
+ }
+ }
+#endif
AudioMessage *ap = new
AudioMessage(aMsg.BitDepth(), aMsg.Channels(), aMsg.Samples(),