/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
/
/**
* PURPOSE:
*
* rView sound ``viewer'' for playing back MDD as audio samples.
* This file consists of two parts: the highly platform dependent
* SoundPlayer class providing the actual low-level sound playback
* and the general purpose wxWindows class rviewSoundPlayer that
* implements a typical rView display mode window and playback
* controls.
* The SoundPlayer class currently has implementations for Solaris
* and WindowsNT. Supporting other Unix brands only requires
* changes to SoundPlayer::configureDevice, supporting other
* platforms is considerably more complicated (see Unix vs. NT
* implementations).
*
* COMMENTS:
* None
*/
// Standard wxWindows preamble.
#ifdef __GNUG__
#pragma implementation
#endif
#ifndef __HAL_ONLY__
// changed in wxWindows 2.4.2:
//#include "wx_prec.h"
#include
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include
#endif
#endif // HAL
/* All platforms */
#include
#include
#include
#include
#include
#include
/* Platform class (e.g. Unix) */
#ifndef __VISUALC__
#include
#include
/* Platform specific */
#ifdef __sun
#include
#endif
#endif
#ifndef __HAL_ONLY__
#ifdef EARLY_TEMPLATE
#define __EXECUTABLE__
#endif
#include "raslib/rmdebug.hh"
#include "raslib/primitivetype.hh"
#include "raslib/minterval.hh"
//#include "rasodmg/odmgtypes.hh"
#include "rasodmg/marray.hh"
#include "rasodmg/ref.hh"
#endif // HAL
#include "rviewSound.hh"
#ifndef __HAL_ONLY__
#include "rviewTypes.hh"
#include "rviewPrefs.hh"
#include "labelManager.hh"
#endif // HAL
/* Minimum size of ulaw table */
const int ULAW_LD_TABLE_MIN=10;
/* log2 of the length of a linear segment in ulaw coding */
const int ULAW_LD_LINEAR_SIZE=7;
// general debug messages (should only enable on Unix)
//#define SOUND_PLAYER_DEBUG
// Debug output to file?
//#define SOUND_DEBUG_FILE "Z:\\dehmel\\rview\\slog"
const int rviewSoundPlayer::sound_bwidth = 50;
const int rviewSoundPlayer::sound_bheight = 30;
const int rviewSoundPlayer::sound_sheight = 50;
const int rviewSoundPlayer::sound_twidth = 120;
const int rviewSoundPlayer::sound_theight = 50;
const int rviewSoundPlayer::sound_cwidth = 120;
const int rviewSoundPlayer::sound_cheight = 30;
const int rviewSoundPlayer::sound_ctrly = rviewSoundPlayer::sound_bheight + rviewSoundPlayer::sound_theight + rviewSoundPlayer::sound_sheight + 5*rviewDisplay::display_border;
const int rviewSoundPlayer::sound_width = rviewDisplay::display_width;
const int rviewSoundPlayer::sound_height = rviewDisplay::display_cheight + rviewSoundPlayer::sound_ctrly + 2*rviewDisplay::display_border;
const int rviewSoundPlayer::sound_latencies = 11;
/* Global variables and functions */
static soundPlayer *activePlayer = NULL;
static int inCallback = 0;
#ifdef SOUND_DEBUG_FILE
static FILE *debugfd=NULL;
#endif
#ifdef __VISUALC__
VOID CALLBACK handle_sound_timer(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
#ifdef SOUND_PLAYER_DEBUG
cout << "timer called, time " << dwTime << endl;
#endif
if ((activePlayer != NULL) && (inCallback == 0))
{
inCallback = 1;
activePlayer->writeSamples(dwTime);
inCallback = 0;
}
}
#else
static void handle_sound_timer(int signal)
{
#ifdef SOUND_PLAYER_DEBUG
cout << "timer called " << signal << ", player " << (void*)activePlayer << ", inCallback " << inCallback << endl;
#endif
if ((activePlayer != NULL) && (inCallback == 0))
{
inCallback = 1;
activePlayer->writeSamples();
inCallback = 0;
}
}
#endif
/*
* soundPlayer: low-level sound driver, hardware abstraction layer
*/
soundPlayer::soundPlayer(void)
{
setupVariables();
}
soundPlayer::soundPlayer(int frq, int ch, FILE *fp, rviewSoundFormat fmt, int lat)
{
setupVariables();
newSample(frq, ch, fp, fmt, lat);
}
soundPlayer::soundPlayer(int frq, int ch, const signed char *data, int len, rviewSoundFormat fmt, int lat)
{
setupVariables();
newSample(frq, ch, data, len, fmt, lat);
}
soundPlayer::soundPlayer(int frq, int ch, const unsigned char *data, int len, rviewSoundFormat fmt, int lat)
{
setupVariables();
newSample(frq, ch, data, len, fmt, lat);
}
soundPlayer::soundPlayer(int frq, int ch, const short *data, int len, rviewSoundFormat fmt, int lat)
{
setupVariables();
newSample(frq, ch, data, len, fmt, lat);
}
soundPlayer::~soundPlayer(void)
{
playbackStop();
if (buffer != NULL) delete [] buffer;
if (convBuff != NULL) delete [] convBuff;
if (LinToUlaw != NULL) delete [] LinToUlaw;
if (UlawToLin != NULL) delete [] UlawToLin;
}
void soundPlayer::setupVariables(void)
{
buffer = NULL; convBuff = NULL; inData = NULL; sampleFile = NULL; suspendedPlayer = NULL;
LinToUlaw = NULL; UlawToLin = NULL; timerActive = FALSE; loopMode = 0;
#ifdef __VISUALC__
waveOut = (HWAVEOUT)0; timerID = 0;
for (int i=0; i= ulawsize) return;
delete [] LinToUlaw;
}
if (ulawsize < ULAW_LD_TABLE_MIN) ldUlawSize = ULAW_LD_TABLE_MIN; else ldUlawSize = ulawsize;
LinToUlaw = new unsigned char[(1<> vsh;
val = base - sign * val;
*u++ = val;
}
}
}
i = (1<<(ldUlawSize-1)) - range;
memset(LinToUlaw, LinToUlaw[i], i-1);
memset(LinToUlaw + (1<> 4);
*data++ = -((((1 << j) - 1) << ULAW_LD_LINEAR_SIZE) + ((16-(i&15)) << (j + ULAW_LD_LINEAR_SIZE - 4)));
}
for (i=128; i<256; i++)
{
j = ((255 - i) >> 4);
*data++ = ((((1 << j) -1) << ULAW_LD_LINEAR_SIZE) + ((15-(i&15)) << (j + ULAW_LD_LINEAR_SIZE - 4)));
}
/*for (i=0; i<32; i++)
{
printf("%4x: ", i*8);
for (j=0; j<8; j++)
{
printf("%6d ", UlawToLin[8*i + j]);
}
printf("\n");
}*/
}
char *soundPlayer::ensureConvBuff(int size)
{
if (convBuff == NULL)
{
convBuff = new char [size]; cbuffSize = size;
}
else
{
if (cbuffSize < size)
{
delete [] convBuff; convBuff = new char [size]; cbuffSize = size;
}
}
return convBuff;
}
char *soundPlayer::ensureSampleBuff(int size)
{
if (buffer == NULL)
{
buffer = new char[size]; buffSize = size;
}
else
{
if (buffSize < size)
{
delete [] buffer; buffer = new char[size]; buffSize = size;
}
}
return buffer;
}
const char *soundPlayer::ensureSamplesForDevice(const char *source, int len)
{
int needSize;
int needSamples;
int i;
#ifdef SOUND_PLAYER_DEBUG
cout << "soundPlayer::ensureSamplesForDevice" << endl;
#endif
if (format == devFormat) return source;
needSamples = len * channels; needSize = len * devSampSize;
ensureConvBuff(needSize);
// Device is 8 bit signed linear (mean at 0)
if (devFormat == rsf_lin8)
{
signed char *dest = (signed char*)convBuff;
if (format == rsf_ulin8)
{
const unsigned char *src = (const unsigned char*)source;
for (i=0; i> 8);
}
else if (format == rsf_lin16)
{
const short *src = (const short *)source;
for (i=0; i> 8);
}
}
// Device is 8 bit unsigned linear (mean at 0x80)
else if (devFormat == rsf_ulin8)
{
unsigned char *dest = (unsigned char*)convBuff;
if (format == rsf_lin8)
{
const signed char *src = (const signed char*)source;
for (i=0; i> 8) + 0x80);
}
else if (format == rsf_lin16)
{
const short *src = (const short*)source;
for (i=0; i> 8) + 0x80);
}
}
// Device is 8 bit ulaw
else if (devFormat == rsf_ulaw8)
{
unsigned char *dest = (unsigned char*)convBuff;
if (format == rsf_lin8)
{
const signed char *src = (const signed char*)source;
short val;
ensureUlawTable(8);
for (i=0; i> (16 - ldUlawSize))];
}
}
else if (format == rsf_ulin8)
{
const unsigned char *src = (const unsigned char*)source;
short val;
ensureUlawTable(8);
for (i=0; i> (16 - ldUlawSize))];
}
}
else if (format == rsf_lin16)
{
const short *src = (const short*)source;
short val;
ensureUlawTable(14);
for (i=0; i> (16 - ldUlawSize))];
}
}
}
// Device is 16 bit linear
else if (devFormat == rsf_lin16)
{
short *dest = (short*)convBuff;
if (format == rsf_lin8)
{
const signed char *src = (const signed char*)source;
for (i=0; i 0)
{
dsize = fread(b, sampleSize, total, sampleFile);
dataOffset += dsize;
if (dsize < total)
{
fseek(sampleFile, 0, SEEK_SET); dataOffset = 0;
}
b += dsize * sampleSize; total -= dsize;
}
}
if (handleOutOfData(num) != 0)
{
sampleFile = NULL; return NULL;
}
result = ensureSamplesForDevice(buffer, num);
}
else if (inData != NULL)
{
if (loopMode == 0)
{
if (num + dataOffset > inLength) num = inLength - dataOffset;
result = (char*)inData + dataOffset * sampleSize;
dataOffset += num;
}
else
{
int total, dsize;
ensureSampleBuff(num * sampleSize);
b = buffer; total = num;
while (total > 0)
{
dsize = inLength - dataOffset;
if (dsize > total) dsize = total;
memcpy(b, inData + dataOffset * sampleSize, dsize * sampleSize);
dataOffset += dsize; if (dataOffset >= inLength) dataOffset = 0;
b += dsize * sampleSize; total -= dsize;
}
result = buffer;
}
if (handleOutOfData(num) != 0)
{
inData = NULL; return NULL;
}
result = ensureSamplesForDevice(result, num);
}
else
{
playbackStop(); result = NULL; num = 0;
}
return result;
}
int soundPlayer::handleOutOfData(int dataSize)
{
// If there is data, do nothing.
if (dataSize > 0) return 0;
#ifdef __VISUALC__
// On Windows we have to make sure both buffers are played to the end.
// Since the new one is all empty that leaves only the current one,
// therefore delay by 1 buffer.
if (emptyBuffers < 1)
{
emptyBuffers++; return 0;
}
#endif
// On Unix we can stop immediately
playbackStop();
return 1;
}
int soundPlayer::playbackSetPosition(int position)
{
int oldPosition = -1;
oldPosition = dataOffset;
if (position >= 0)
{
if (sampleFile != NULL)
{
fseek(sampleFile, position, SEEK_SET);
dataOffset = (int)ftell(sampleFile);
}
else
{
dataOffset = (position < inLength) ? position : inLength-1;
}
}
return oldPosition;
}
int soundPlayer::playbackLoopMode(int lpMode)
{
int oldLoop = loopMode;
loopMode = lpMode;
return oldLoop;
}
#ifdef __VISUALC__
void soundPlayer::freeWaveHeaders(void)
{
int i;
for (i=0; iplaybackSuspend();
suspendedPlayer = activePlayer;
}
}
activePlayer = this;
#ifdef __VISUALC__
lastSyncTime = GetTickCount();
#else
struct timezone tzp;
gettimeofday(&lastSyncTime, &tzp);
#endif
// period in us
period = (unsigned int)(1000 * latency * RVIEW_SND_RELPERIOD);
if (setTimerInterval(period) != 0)
{
cerr << "Unable to set up timer!" << endl;
return -1;
}
#ifdef SOUND_PLAYER_DEBUG
cout << "started timer with period " << period << endl;
#endif
return 0;
}
int soundPlayer::stopTimer(int ap)
{
if (!timerActive) return -1;
setTimerInterval(0);
timerActive = FALSE;
activePlayer = NULL;
if (ap != 0)
{
if (suspendedPlayer != NULL)
{
activePlayer = suspendedPlayer; suspendedPlayer = NULL;
activePlayer->playbackResume();
}
}
return 0;
}
#ifdef __VISUALC__
void soundPlayer::writeSamples(DWORD systime)
#else
void soundPlayer::writeSamples(void)
#endif
{
int samplesNeeded;
#ifdef __VISUALC__
samplesNeeded = ((systime - lastSyncTime) * frequency) / 1000;
#else
struct timeval tp;
struct timezone tzp;
float usecs;
gettimeofday(&tp, &tzp);
usecs = (float)(tp.tv_usec - lastSyncTime.tv_usec);
samplesNeeded = (tp.tv_sec - lastSyncTime.tv_sec) * frequency + (int)((usecs * frequency) / 1e6);
#endif
#ifdef SOUND_PLAYER_DEBUG
cout << "soundPlayer::writeSamples" << endl;
#endif
#ifdef SOUND_DEBUG_FILE
fprintf(debugfd, "%d: written: %d, needed: %d, deltawa: %d\n", systime, samplesWritten, samplesNeeded, samplesWritten - samplesNeeded - samplesWriteahead);
#endif
if ((samplesWritten - samplesNeeded) >= samplesWriteahead)
{
#ifdef SOUND_PLAYER_DEBUG
cout << "soundPlayer: stalled" << endl;
#endif
samplesWritten = (samplesWritten - samplesNeeded);
#ifdef __VISUALC__
lastSyncTime = systime;
#else
lastSyncTime.tv_sec = tp.tv_sec; lastSyncTime.tv_usec = tp.tv_usec;
#endif
#ifdef SOUND_DEBUG_FILE
fprintf(debugfd, "stalled\n");
#endif
}
else
{
int num;
#ifdef SOUND_PLAYER_DEBUG
cout << "written " << samplesWritten << ", needed " << samplesNeeded << endl;
#endif
// Underflow?
if ((samplesWritten - samplesNeeded) < 0)
{
samplesWritten = samplesNeeded;
#ifdef SOUND_DEBUG_FILE
fprintf(debugfd, "underflow\n");
#endif
}
//num = samplesWritten - samplesNeeded;
num = samplesWriteahead;
if (num != 0)
{
const char *newSamples;
#ifdef SOUND_PLAYER_DEBUG
cout << "samples " << num << ", device " << endl;
#endif
if ((newSamples = ensureSamples(num)) != NULL)
{
#ifdef __VISUALC__
int bsize = waveHdrs[currentHeader].dwBufferLength;
#ifdef SOUND_DEBUG_FILE
fprintf(debugfd, "need %d, buff %d, flags %x\n", num, bsize, waveHdrs[currentHeader].dwFlags);
#endif
// If the buffer is still being used we do nothing.
if ((waveHdrs[currentHeader].dwFlags & (WHDR_INQUEUE | WHDR_DONE)) != WHDR_DONE) return;
#ifdef SOUND_DEBUG_FILE
fprintf(debugfd, "fill Buffer %d\n", currentHeader);
#endif
//waveOutUnprepareHeader(waveOut, waveHdrs + currentHeader, sizeof(WAVEHDR));
// must prepare the header here or no playback.
//waveHdrs[currentHeader].dwFlags = 0;
waveOutPrepareHeader(waveOut, waveHdrs + currentHeader, sizeof(WAVEHDR));
memcpy(waveHdrs[currentHeader].lpData, newSamples, num * devSampSize);
// Fill rest of buffer with the correct 0 value
if (num * devSampSize != bsize)
{
int fillValue = 0;
memset(waveHdrs[currentHeader].lpData + num * devSampSize, fillValue, bsize - num * devSampSize);
}
waveOutWrite(waveOut, waveHdrs + currentHeader, sizeof(WAVEHDR));
currentHeader++; if (currentHeader >= RVIEW_SND_BUFFERS) currentHeader = 0;
samplesWritten += samplesWriteahead;
#else
write(audioDevice, newSamples, num * devSampSize);
samplesWritten += num;
#endif
}
#ifdef SOUND_PLAYER_DEBUG
cout << "soundPlayer: wrote " << num << " samples" << endl;
#endif
}
}
}
#ifndef __HAL_ONLY__
// Descriptor for sound formats
const rviewSoundPlayer::format_desc rviewSoundPlayer::soundFormatDesc[] = {
{"soundFmtLin8", rsf_lin8, 1},
{"soundFmtUlin8", rsf_ulin8, 1},
{"soundFmtUlaw8", rsf_ulaw8, 1},
{"soundFmtLin16", rsf_lin16, 2},
{NULL, rsf_none, 0}
};
/*
* rviewSoundPlayer: sound player widget, platform independent.
*/
rviewSoundPlayer::rviewSoundPlayer(mdd_frame *mf, unsigned int flags) : rviewDisplay(mf, sound_ctrly, flags)
{
int w, h;
char buffer[STRINGSIZE];
char **latStr, **fmtStr;
int fnumLin8, fnumUlaw8, fnumLin16;
char *b;
int i;
RMDBGENTER(3, RMDebug::module_applications, "rviewSoundPlayer", "rviewSoundPlayer()");
#if 0
{
dimMDD = 1; interv = r_Minterval(1);
//interv << r_Sinterval(r_Range(0), r_Range(41744));
//#define SAMPLE_NAME "death.sam"
//interv << r_Sinterval(r_Range(0), r_Range(79842));
//#define SAMPLE_NAME "cyber.sam"
interv << r_Sinterval(r_Range(0), r_Range(77071));
#define SAMPLE_NAME "willy.sam"
r_Ref > mddPtr = new r_Marray(interv);
mddPtr->set_type_by_name("OctetString");
sprintf(buffer, "marray ", interv[0].high());
mddPtr->set_type_structure(buffer);
char *data = mddPtr->get_array();
#ifdef __VISUALC__
FILE *fp = fopen("Z:\\dehmel\\rview\\samples\\" SAMPLE_NAME, "rb");
#else
FILE *fp = fopen("samples" DIR_SEPARATOR SAMPLE_NAME, "rb");
#endif
if (fp != NULL)
{
fread(data, 1, interv[0].high() - interv[0].low() + 1, fp); fclose(fp);
}
else
{
memset(data, 0x80, interv[0].high() - interv[0].low() + 1);
}
mddObj = (r_Ref)mddPtr; baseType = rbt_uchar;
}
#endif
sampleBuffer = NULL; lastOffset = 0; paused = FALSE;
typeLength = mddObj->get_type_length(); playbackOn = FALSE;
// Defaults
frequency = prefs->soundFreq; latency = prefs->soundLatency; loopMode = prefs->soundLoop;
GetClientSize(&w, &h);
toStart = new rviewButton(ctrlPanel, "<<");
toEnd = new rviewButton(ctrlPanel, ">>");
pbPause = new rviewButton(ctrlPanel, "||");
pbStart = new rviewButton(ctrlPanel, ">");
pbStop = new rviewButton(ctrlPanel, "[]");
pbLoop = new rviewButton(ctrlPanel);
slider = new rviewSlider(ctrlPanel, 0, 0, 1000, 10, lman->lookup("soundPlayTime"));
frqWidget = new rviewText(ctrlPanel, frequency);
fnumLin8 = 0; fnumUlaw8 = 0; fnumLin16 = 0;
for (i=0; soundFormatDesc[i].labelName != NULL; i++)
{
switch (soundFormatDesc[i].fmt)
{
case rsf_lin8: fnumLin8 = i; break;
case rsf_ulaw8: fnumUlaw8 = i; break;
case rsf_lin16: fnumLin16 = i; break;
default: break;
}
}
fmtStr = new char *[i];
for (i=0; soundFormatDesc[i].labelName != NULL; i++)
fmtStr[i] = lman->lookup(soundFormatDesc[i].labelName);
fmtWidget = new rviewChoice(ctrlPanel, i, fmtStr, lman->lookup("soundFormat"));
delete [] fmtStr;
latencies = new int[sound_latencies];
for (i=0; ilookup("soundLatency"));
delete [] latStr;
for (i=0; i latency)) break;
}
latWidget->SetSelection(i);
b = projString;
b += sprintf(b, "*:*");
for (i=1; iSetValue(projString);
// Interpret 2D data as multiple channels
setModeDimension((dimMDD == 1) ? 1 : 2);
setLoopMode(loopMode);
// Mustn't create errorbox before all widgets are created.
switch (baseType)
{
case rbt_char: currentFormat = fnumUlaw8; break;
case rbt_uchar: currentFormat = fnumLin8; break;
case rbt_short: currentFormat = fnumLin16; break;
default:
{
rviewErrorbox::reportError(lman->lookup("errorSoundFormat"), rviewSoundPlayer::getFrameName(), "rviewSoundFormat");
currentFormat = -1;
objectInitializedOK = FALSE;
}
break;
}
if (currentFormat >= 0) fmtWidget->SetSelection(currentFormat);
RMDBGEXIT(3, RMDebug::module_applications, "rviewSoundPlayer", "rviewSoundPlayer()");
}
int rviewSoundPlayer::openViewer(void)
{
RMDBGONCE(3, RMDebug::module_applications, "rviewSoundPlayer", "openViewer()");
if (currentFormat < 0)
{
rviewErrorbox::reportError(lman->lookup("errorSoundFormat"), rviewSoundPlayer::getFrameName(), "openViewer");
objectInitializedOK = FALSE;
return -1;
}
if (rviewDisplay::openViewer() == 0)
{
int w, h;
GetClientSize(&w, &h);
label();
frameWidth=-1;
frameHeight=-1;
OnSize(w, h);
OnSize(w, h);
Show(TRUE);
return 0;
}
return -1;
}
rviewSoundPlayer::~rviewSoundPlayer(void)
{
RMDBGONCE(3, RMDebug::module_applications, "rviewSoundPlayer", "~rviewSoundPlayer()");
closeViewer();
if (latencies)
{
delete [] latencies;
latencies=0;
}
if (sampleBuffer)
{
delete [] sampleBuffer;
sampleBuffer=0;
}
}
const char *rviewSoundPlayer::getFrameName(void) const
{
return "rviewSoundPlayer";
}
rviewFrameType rviewSoundPlayer::getFrameType(void) const
{
return rviewFrameTypeSound;
}
int rviewSoundPlayer::getViewerType(void) const
{
return RVIEW_RESDISP_SOUND;
}
bool rviewSoundPlayer::setLoopMode(bool lm)
{
bool oldMode = loopMode;
loopMode = lm;
if (loopMode)
{
pbLoop->SetLabel("<-->");
}
else
{
pbLoop->SetLabel("--->");
}
player.playbackLoopMode((loopMode) ? 1 : 0);
return oldMode;
}
void rviewSoundPlayer::setSlider(int offset)
{
slider->SetValue((offset + frequency - 1) / frequency);
}
void rviewSoundPlayer::label(void)
{
SetTitle(lman->lookup("titleSound"));
slider->SetLabel(lman->lookup("soundPlayTime"));
frqWidget->SetLabel(lman->lookup("soundFrequency"));
latWidget->SetLabel(lman->lookup("soundLatency"));
rviewDisplay::label();
}
int rviewSoundPlayer::process(wxObject &obj, wxEvent &evt)
{
int type = evt.GetEventType();
RMDBGONCE(3, RMDebug::module_applications, "rviewSoundPlayer", "process(...)");
if (rviewDisplay::process(obj, evt) != 0)
{
return 1;
}
if (type == wxEVENT_TYPE_BUTTON_COMMAND)
{
if (&obj == (wxObject*)pbStart)
{
startPlayback();
return 1;
}
else if (&obj == (wxObject*)pbStop)
{
stopPlayback();
return 1;
}
else if (&obj == (wxObject*)toStart)
{
player.playbackSetPosition(0);
setSlider(0);
return 1;
}
else if (&obj == (wxObject*)toEnd)
{
player.playbackSetPosition(sampleLength);
setSlider(sampleLength);
return 1;
}
else if (&obj == (wxObject*)pbPause)
{
if (paused)
{
player.playbackResume(); paused = FALSE;
}
else
{
player.playbackSuspend(); paused = TRUE;
}
return 1;
}
else if (&obj == (wxObject*)pbLoop)
{
setLoopMode(!loopMode);
return 1;
}
}
if (type == wxEVENT_TYPE_SLIDER_COMMAND)
{
if (&obj == (wxObject*)slider)
{
int soff, poff;
if ((poff = player.playbackGetOffset()) >= 0)
{
soff = slider->GetValue();
if (soff != poff/frequency)
{
player.playbackSetPosition(soff * frequency);
}
}
return 1;
}
}
if (type == wxEVENT_TYPE_CHOICE_COMMAND)
{
if (&obj == (wxObject*)fmtWidget)
{
int newFmt;
newFmt = fmtWidget->GetSelection();
if ((soundFormatDesc[newFmt].sampleSize != baseSize) && (currentFormat >= 0))
{
fmtWidget->SetSelection(currentFormat);
}
else
{
currentFormat = newFmt;
}
return 1;
}
}
return 0;
}
void rviewSoundPlayer::OnSize(int w, int h)
{
int x, y, posx, posy, d;
RMDBGONCE(3, RMDebug::module_applications, "rviewSoundPlayer", "OnSize( " << w << ", " << h << " )");
rviewDisplay::OnSize(w, h);
GetClientSize(&x, &y);
//need to resize?
if (( sound_width != x) || ( sound_height != y))
{
frameWidth = sound_width;
frameHeight = sound_height;
x = sound_width;
y = sound_height;
SetClientSize(x, y);
return;
}
d = (x - 7*display_border) / 6;
posx = display_border; posy = display_border + display_cheight;
toStart->SetSize(posx, posy, d, sound_bheight);
posx += d + display_border;
pbPause->SetSize(posx, posy, d, sound_bheight);
posx += d + display_border;
pbStart->SetSize(posx, posy, d, sound_bheight);
posx += d + display_border;
pbStop->SetSize(posx, posy, d, sound_bheight);
posx += d + display_border;
toEnd->SetSize(posx, posy, d, sound_bheight);
posx += d + display_border;
pbLoop->SetSize(posx, posy, d, sound_bheight);
posx = display_border; posy += sound_bheight + display_border;
d = (x - 4*display_border) / 3;
frqWidget->SetSize(posx, posy, d, sound_theight);
fmtWidget->SetSize(posx + d + display_border, posy, 6*d/9, sound_cheight);
latWidget->SetSize(posx + 2*(d + display_border), posy, 5*d/9, sound_cheight);
posy += sound_theight + 2*display_border;
slider->SetSize(display_border, posy, x - 2*display_border, sound_theight);
}
int rviewSoundPlayer::newProjection(void)
{
RMDBGONCE(3, RMDebug::module_applications, "rviewSoundPlayer", "newProjection()");
if (playbackOn)
{
player.playbackStop();
if (buildSample() != 0) return -1;
if (newSample() != 0) return -1; // implicitly does playbackResume()
}
else
{
return startPlayback();
}
return 0;
}
void rviewSoundPlayer::prepareToDie(void)
{
//cout << "rviewSoundPlayer::prepareToDie" << endl;
stopPlayback();
::wxYield();
}
int rviewSoundPlayer::newSample(void)
{
int fmt;
int status=0;
RMDBGONCE(3, RMDebug::module_applications, "rviewSoundPlayer", "newSample()");
frequency = atoi(frqWidget->GetValue());
latency = latencies[latWidget->GetSelection()];
fmt = fmtWidget->GetSelection();
switch (fmt)
{
case 0:
status = player.newSample(frequency, channels, (signed char*)sampleBuffer, sampleLength, rsf_lin8, latency);
break;
case 1:
status = player.newSample(frequency, channels, (unsigned char *)sampleBuffer, sampleLength, rsf_ulin8, latency);
break;
case 2:
status = player.newSample(frequency, channels, (unsigned char *)sampleBuffer, sampleLength, rsf_ulin8, latency);
break;
case 3:
status = player.newSample(frequency, channels, (short *)sampleBuffer, sampleLength, rsf_lin16, latency);
break;
default:
{
rviewErrorbox::reportError(lman->lookup("errorSoundFormat"), rviewSoundPlayer::getFrameName(), "newSample");
}
return -1;
}
if (status != 0)
{
rviewErrorbox::reportError(lman->lookup("errorSoundDevice"), rviewSoundPlayer::getFrameName(), "newSample");
return -1;
}
setSlider(0);
slider->SetRange(0, (sampleLength + frequency - 1) / frequency);
return 0;
}
int rviewSoundPlayer::buildSample(void)
{
int stepx, stepy;
union {char *c; short *s;} src, dest, srcBase;
r_Ref > mddPtr = (r_Ref >)mddObj;
char *base;
int i;
RMDBGONCE(3, RMDebug::module_applications, "rviewSoundPlayer", "buildSample()");
strcpy(projString, project->GetValue());
if (rviewParseProjection(getVirtualDomain(), pt1, pt2, projString, &freeDims) != dimMDD)
{
rviewErrorbox::reportError(lman->lookup("errorProjection"), rviewSoundPlayer::getFrameName(), "buildSample");
return -1;
}
dim1 = dimMDD; dim2 = dimMDD;
for (dim1=0; dim1get_array();
src.c = base + typeLength * ((char*)(&((*mddPtr)[pt1])) - base);
r_Point paux(pt1);
paux[dim1]++;
stepx = (int)(&((*mddPtr)[paux]) - &((*mddPtr)[pt1]));
// One channel or multiple ones?
if (dim2 >= dimMDD)
{
channels = 1;
sampleBuffer = (void*)(new char[sampleLength * typeLength]);
dest.c = (char*)sampleBuffer;
switch (typeLength)
{
case 1:
{
for (i=0; i create channel-interleaved sample data.
switch (typeLength)
{
case 1:
{
for (i=0; i= 0)
{
if (abs(offset - lastOffset) >= frequency)
{
slider->SetValue(offset / frequency);
lastOffset = offset;
}
::wxYield();
if (!playbackOn) break;
}
if (offset < 0)
{
setSlider(sampleLength);
}
playbackOn = FALSE;
return 0;
}
int rviewSoundPlayer::stopPlayback(void)
{
player.playbackStop();
playbackOn = FALSE;
return 0;
}
#else
// Testbed
int main(int argc, char *argv[])
{
FILE *infile;
soundPlayer *sp;
#ifdef __VISUALC__
char *lumpname = "samples\\death.sam";
#else
char *lumpname = "samples/death.sam";
#endif
int offset, lastOffset;
int frequency;
if (argc > 1)
{
lumpname = argv[1];
}
if ((infile = fopen(lumpname, "rb")) == NULL)
{
cerr << "Couldn't open file " << lumpname << endl;
exit(-1);
}
cout << "create new player" << endl;
frequency = 11025;
sp = new soundPlayer(frequency, 1, infile, rsf_ulin8, 500);
lastOffset = -frequency;
while ((offset = sp->playbackActive()) >= 0)
{
if (abs(offset - lastOffset) >= frequency)
{
printf("Time %ds\r", offset / frequency); fflush(stdout);
lastOffset = offset;
}
}
printf("\n", offset);
cout << "delete player" << endl;
delete sp;
fclose(infile);
return 0;
}
#endif // HAL