summaryrefslogtreecommitdiff
authorllornkcor <llornkcor>2002-07-24 15:18:26 (UTC)
committer llornkcor <llornkcor>2002-07-24 15:18:26 (UTC)
commit9e126f7ed2f73b26ef440c1cc54d0dc0e6308f68 (patch) (side-by-side diff)
treee118086859eb8bee05bf39bbb8d7c2442c785547
parent919228ff6aeb72b6d2585ae108e86d27d0b6bdb1 (diff)
downloadopie-9e126f7ed2f73b26ef440c1cc54d0dc0e6308f68.zip
opie-9e126f7ed2f73b26ef440c1cc54d0dc0e6308f68.tar.gz
opie-9e126f7ed2f73b26ef440c1cc54d0dc0e6308f68.tar.bz2
added adpcm hidden config, and fixed tmp file moving before recording.. heh
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--core/applets/vmemo/adpcm.c252
-rw-r--r--core/applets/vmemo/adpcm.h19
-rw-r--r--core/applets/vmemo/vmemo.cpp134
-rw-r--r--core/applets/vmemo/vmemo.h2
-rw-r--r--core/applets/vmemo/vmemo.pro4
5 files changed, 324 insertions, 87 deletions
diff --git a/core/applets/vmemo/adpcm.c b/core/applets/vmemo/adpcm.c
new file mode 100644
index 0000000..c4dfa50
--- a/dev/null
+++ b/core/applets/vmemo/adpcm.c
@@ -0,0 +1,252 @@
+/***********************************************************
+Copyright 1992 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+** Intel/DVI ADPCM coder/decoder.
+**
+** The algorithm for this coder was taken from the IMA Compatability Project
+** proceedings, Vol 2, Number 2; May 1992.
+**
+** Version 1.2, 18-Dec-92.
+**
+** Change log:
+** - Fixed a stupid bug, where the delta was computed as
+** stepsize*code/4 in stead of stepsize*(code+0.5)/4.
+** - There was an off-by-one error causing it to pick
+** an incorrect delta once in a blue moon.
+** - The NODIVMUL define has been removed. Computations are now always done
+** using shifts, adds and subtracts. It turned out that, because the standard
+** is defined using shift/add/subtract, you needed bits of fixup code
+** (because the div/mul simulation using shift/add/sub made some rounding
+** errors that real div/mul don't make) and all together the resultant code
+** ran slower than just using the shifts all the time.
+** - Changed some of the variable names to be more meaningful.
+*/
+
+#include "adpcm.h"
+#include <stdio.h> /*DBG*/
+
+#ifndef __STDC__
+#define signed
+#endif
+
+/* Intel ADPCM step variation table */
+static int indexTable[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+static int stepsizeTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+void
+adpcm_coder(indata, outdata, len, state)
+ short indata[];
+ char outdata[];
+ int len;
+ struct adpcm_state *state;
+{
+ short *inp; /* Input buffer pointer */
+ signed char *outp; /* output buffer pointer */
+ int val; /* Current input sample value */
+ int sign; /* Current adpcm sign bit */
+ int delta; /* Current adpcm output value */
+ int diff; /* Difference between val and valprev */
+ int step; /* Stepsize */
+ int valpred; /* Predicted output value */
+ int vpdiff; /* Current change to valpred */
+ int index; /* Current step change index */
+ int outputbuffer; /* place to keep previous 4-bit value */
+ int bufferstep; /* toggle between outputbuffer/output */
+
+ outp = (signed char *)outdata;
+ inp = indata;
+
+ valpred = state->valprev;
+ index = state->index;
+ step = stepsizeTable[index];
+
+ bufferstep = 1;
+
+ for ( ; len > 0 ; len-- ) {
+ val = *inp++;
+
+ /* Step 1 - compute difference with previous value */
+ diff = val - valpred;
+ sign = (diff < 0) ? 8 : 0;
+ if ( sign ) diff = (-diff);
+
+ /* Step 2 - Divide and clamp */
+ /* Note:
+ ** This code *approximately* computes:
+ ** delta = diff*4/step;
+ ** vpdiff = (delta+0.5)*step/4;
+ ** but in shift step bits are dropped. The net result of this is
+ ** that even if you have fast mul/div hardware you cannot put it to
+ ** good use since the fixup would be too expensive.
+ */
+ delta = 0;
+ vpdiff = (step >> 3);
+
+ if ( diff >= step ) {
+ delta = 4;
+ diff -= step;
+ vpdiff += step;
+ }
+ step >>= 1;
+ if ( diff >= step ) {
+ delta |= 2;
+ diff -= step;
+ vpdiff += step;
+ }
+ step >>= 1;
+ if ( diff >= step ) {
+ delta |= 1;
+ vpdiff += step;
+ }
+
+ /* Step 3 - Update previous value */
+ if ( sign )
+ valpred -= vpdiff;
+ else
+ valpred += vpdiff;
+
+ /* Step 4 - Clamp previous value to 16 bits */
+ if ( valpred > 32767 )
+ valpred = 32767;
+ else if ( valpred < -32768 )
+ valpred = -32768;
+
+ /* Step 5 - Assemble value, update index and step values */
+ delta |= sign;
+
+ index += indexTable[delta];
+ if ( index < 0 ) index = 0;
+ if ( index > 88 ) index = 88;
+ step = stepsizeTable[index];
+
+ /* Step 6 - Output value */
+ if ( bufferstep ) {
+ outputbuffer = (delta << 4) & 0xf0;
+ } else {
+ *outp++ = (delta & 0x0f) | outputbuffer;
+ }
+ bufferstep = !bufferstep;
+ }
+
+ /* Output last step, if needed */
+ if ( !bufferstep )
+ *outp++ = outputbuffer;
+
+ state->valprev = valpred;
+ state->index = index;
+}
+
+void
+adpcm_decoder(indata, outdata, len, state)
+ char indata[];
+ short outdata[];
+ int len;
+ struct adpcm_state *state;
+{
+ signed char *inp; /* Input buffer pointer */
+ short *outp; /* output buffer pointer */
+ int sign; /* Current adpcm sign bit */
+ int delta; /* Current adpcm output value */
+ int step; /* Stepsize */
+ int valpred; /* Predicted value */
+ int vpdiff; /* Current change to valpred */
+ int index; /* Current step change index */
+ int inputbuffer; /* place to keep next 4-bit value */
+ int bufferstep; /* toggle between inputbuffer/input */
+
+ outp = outdata;
+ inp = (signed char *)indata;
+
+ valpred = state->valprev;
+ index = state->index;
+ step = stepsizeTable[index];
+
+ bufferstep = 0;
+
+ for ( ; len > 0 ; len-- ) {
+
+ /* Step 1 - get the delta value */
+ if ( bufferstep ) {
+ delta = inputbuffer & 0xf;
+ } else {
+ inputbuffer = *inp++;
+ delta = (inputbuffer >> 4) & 0xf;
+ }
+ bufferstep = !bufferstep;
+
+ /* Step 2 - Find new index value (for later) */
+ index += indexTable[delta];
+ if ( index < 0 ) index = 0;
+ if ( index > 88 ) index = 88;
+
+ /* Step 3 - Separate sign and magnitude */
+ sign = delta & 8;
+ delta = delta & 7;
+
+ /* Step 4 - Compute difference and new predicted value */
+ /*
+ ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
+ ** in adpcm_coder.
+ */
+ vpdiff = step >> 3;
+ if ( delta & 4 ) vpdiff += step;
+ if ( delta & 2 ) vpdiff += step>>1;
+ if ( delta & 1 ) vpdiff += step>>2;
+
+ if ( sign )
+ valpred -= vpdiff;
+ else
+ valpred += vpdiff;
+
+ /* Step 5 - clamp output value */
+ if ( valpred > 32767 )
+ valpred = 32767;
+ else if ( valpred < -32768 )
+ valpred = -32768;
+
+ /* Step 6 - Update step value */
+ step = stepsizeTable[index];
+
+ /* Step 7 - Output value */
+ *outp++ = valpred;
+ }
+
+ state->valprev = valpred;
+ state->index = index;
+}
diff --git a/core/applets/vmemo/adpcm.h b/core/applets/vmemo/adpcm.h
new file mode 100644
index 0000000..9c17ffa
--- a/dev/null
+++ b/core/applets/vmemo/adpcm.h
@@ -0,0 +1,19 @@
+/*
+** adpcm.h - include file for adpcm coder.
+**
+** Version 1.0, 7-Jul-92.
+*/
+
+struct adpcm_state {
+ short valprev; /* Previous output value */
+ char index; /* Index into stepsize table */
+};
+
+#ifdef __STDC__
+#define ARGS(x) x
+#else
+#define ARGS(x) ()
+#endif
+
+void adpcm_coder ARGS((short [], char [], int, struct adpcm_state *));
+void adpcm_decoder ARGS((char [], short [], int, struct adpcm_state *));
diff --git a/core/applets/vmemo/vmemo.cpp b/core/applets/vmemo/vmemo.cpp
index b77e3b8..b5239eb 100644
--- a/core/applets/vmemo/vmemo.cpp
+++ b/core/applets/vmemo/vmemo.cpp
@@ -9,16 +9,20 @@
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
************************************************************************************/
// copyright 2002 Jeremy Cowgar <jc@cowgar.com>
/*
* $Id$
*/
// Sun 03-17-2002 L.J.Potter <ljp@llornkcor.com>
+extern "C" {
+#include "adpcm.h"
+}
+
#include <sys/utsname.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
@@ -52,16 +56,23 @@ typedef struct _waveheader {
#define RIFF 0x46464952
#define WAVE 0x45564157
#define FMT 0x20746D66
#define DATA 0x61746164
#define PCM_CODE 1
#define WAVE_MONO 1
#define WAVE_STEREO 2
+struct adpcm_state encoder_state;
+//struct adpcm_state decoder_state;
+
+#define WAVE_FORMAT_DVI_ADPCM (0x0011)
+#define WAVE_FORMAT_PCM (0x0001)
+
+
#include "vmemo.h"
#include <qpe/qpeapplication.h>
#include <qpe/resource.h>
#include <qpe/config.h>
#include <qpainter.h>
#include <qdatetime.h>
@@ -191,33 +202,33 @@ static char * vmemo_xpm[] = {
" P Q R S T U V W X ",
" Y Z ` b ...+. ",
" @.#.$.%.&. ",
" *.B =. ",
" n n n n n n n n n "};
VMemo::VMemo( QWidget *parent, const char *_name )
- : QWidget( parent, _name )
-{
+ : QWidget( parent, _name ) {
setFixedHeight( 18 );
setFixedWidth( 14 );
recording = FALSE;
t_timer = new QTimer( this );
connect( t_timer, SIGNAL( timeout() ), SLOT( timerBreak() ) );
struct utsname name; /* check for embedix kernel running on the zaurus*/
if (uname(&name) != -1) {
QString release=name.release;
Config vmCfg("Vmemo");
vmCfg.setGroup("Defaults");
int toggleKey = setToggleButton(vmCfg.readNumEntry("toggleKey", -1));
+ useADPCM = vmCfg.readBoolEntry("use_ADPCM", 0);
qDebug("toggleKey %d", toggleKey);
if(release.find("embedix",0,TRUE) !=-1)
systemZaurus=TRUE;
else
systemZaurus=FALSE;
@@ -238,65 +249,59 @@ VMemo::VMemo( QWidget *parent, const char *_name )
usingIcon=TRUE;
else
usingIcon=FALSE;
if( vmCfg.readNumEntry("hideIcon",0) == 1)
hide();
}
}
-VMemo::~VMemo()
-{
+VMemo::~VMemo() {
}
-void VMemo::receive( const QCString &msg, const QByteArray &data )
-{
+void VMemo::receive( const QCString &msg, const QByteArray &data ) {
qDebug("receive");
QDataStream stream( data, IO_ReadOnly );
if (msg == "toggleRecord()") {
if (recording) {
fromToggle = TRUE;
mouseReleaseEvent(NULL);
// stopRecording();
} else {
fromToggle = TRUE;
// mousePressEvent(NULL);
startRecording();
}
}
}
-void VMemo::paintEvent( QPaintEvent* )
-{
+void VMemo::paintEvent( QPaintEvent* ) {
QPainter p(this);
p.drawPixmap( 0, 1,( const char** ) vmemo_xpm );
}
-void VMemo::mousePressEvent( QMouseEvent * me)
-{
+void VMemo::mousePressEvent( QMouseEvent * me) {
// just to be safe
if (recording) {
recording = FALSE;
return;
}
/* No mousePress/mouseRelease recording on the iPAQ. The REC button on the iPAQ calls these functions
mousePressEvent and mouseReleaseEvent with a NULL parameter. */
- if ( me->button() != LeftButton)
-
+ if ( me->button() != LeftButton || me != NULL)
// if (!systemZaurus && me != NULL)
return;
if(!recording)
startRecording();
else
stopRecording();
}
-void VMemo::mouseReleaseEvent( QMouseEvent * )
-{
+void VMemo::mouseReleaseEvent( QMouseEvent * ) {
// if(usingIcon && !recording)
// stopRecording();
}
bool VMemo::startRecording() {
if ( recording)
return FALSE;
@@ -370,36 +375,35 @@ bool VMemo::startRecording() {
// if(openWAV(fileName.latin1()) == -1) {
QString err("Could not open the temp file\n");
err += fileName;
QMessageBox::critical(0, "vmemo", err, "Abort");
::close(dsp);
return FALSE;
}
+ record();
+
QString cmd;
cmd.sprintf("mv %s "+fileName,pointer);
-
// move tmp file to regular file here
system(cmd.latin1());
QArray<int> cats(1);
cats[0] = config.readNumEntry("Category", 0);
QString dlName("vm_");
dlName += dt.toString();
DocLnk l;
l.setFile(fileName);
l.setName(dlName);
l.setType("audio/x-wav");
l.setCategories(cats);
l.writeLink();
- record();
-
return TRUE;
}
void VMemo::stopRecording() {
show();
qDebug("Stopped recording");
recording = FALSE;
if(useAlerts) {
@@ -409,18 +413,17 @@ void VMemo::stopRecording() {
}
t_timer->stop();
Config cfg("Vmemo");
cfg.setGroup("Defaults");
if( cfg.readNumEntry("hideIcon",0) == 1 )
hide();
}
-int VMemo::openDSP()
-{
+int VMemo::openDSP() {
Config cfg("Vmemo");
cfg.setGroup("Record");
speed = cfg.readNumEntry("SampleRate", 22050);
channels = cfg.readNumEntry("Stereo", 1) ? 2 : 1; // 1 = stereo(2), 0 = mono(1)
if (cfg.readNumEntry("SixteenBit", 1)==1) {
format = AFMT_S16_LE;
resolution = 16;
@@ -462,150 +465,113 @@ int VMemo::openDSP()
return -1;
}
QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << FALSE; //mute
return 1;
}
-int VMemo::openWAV(const char *filename)
-{
+int VMemo::openWAV(const char *filename) {
track.setName(filename);
if(!track.open(IO_WriteOnly|IO_Truncate|IO_Raw)) {
errorMsg=filename;
return -1;
}
wav=track.handle();
WaveHeader wh;
wh.main_chunk = RIFF;
wh.length=0;
wh.chunk_type = WAVE;
wh.sub_chunk = FMT;
wh.sc_len = 16;
+ if(useADPCM)
+ wh.format = WAVE_FORMAT_DVI_ADPCM;//PCM_CODE;
+ else
wh.format = PCM_CODE;
wh.modus = channels;
wh.sample_fq = speed;
wh.byte_p_sec = speed * channels * resolution/8;
wh.byte_p_spl = channels * (resolution / 8);
wh.bit_p_spl = resolution;
wh.data_chunk = DATA;
wh.data_length= 0;
// qDebug("Write header channels %d, speed %d, b/s %d, blockalign %d, bitrate %d"
// , wh.modus, wh.sample_fq, wh.byte_p_sec, wh.byte_p_spl, wh.bit_p_spl );
write (wav, &wh, sizeof(WaveHeader));
return 1;
}
-void VMemo::record(void)
-{
+void VMemo::record(void) {
int length=0, result, value;
QString msg;
msg.sprintf("Recording format %d", format);
qDebug(msg);
Config config("Vmemo");
config.setGroup("Record");
int sRate=config.readNumEntry("SizeLimit", 30);
t_timer->start( sRate * 1000+1000, TRUE);
- if(systemZaurus) {
+// if(systemZaurus) {
+// } else { // 16 bit only capabilities
- msg.sprintf("Recording format zaurus");
+ msg.sprintf("Recording format other");
qDebug(msg);
- signed short sound[1024], monoBuffer[1024];
-
- if(format==AFMT_S16_LE) {
-
+ int bufsize=1024;
+ int bytesWritten=0;
+ signed short sound[1024], monoBuffer[1024];
+ char abuf[bufsize/2];
+ short sbuf[bufsize];
while(recording) {
+ if(useADPCM)
+ result = read( dsp, sbuf, bufsize); // 8192
+ else
result = read(dsp, sound, 1024); // 8192
- // int j=0;
-
- for (int i = 0; i < result; i++) { //since Z is mono do normally
- monoBuffer[i] = sound[i];
- }
-
- length+=write(wav, monoBuffer, result);
- if(length<0)
- recording=false;
- // for (int i = 0; i < result; i+=2) {
- // monoBuffer[j] = sound[i];
- // // monoBuffer[j] = (sound[i]+sound[i+1])/2;
-
- // j++;
- // }
- qApp->processEvents();
- // printf("%d\r",length);
- // fflush(stdout);
+ if( result <= 0) {
+ perror("recording error ");
+// qDebug(currentFileName);
+ QMessageBox::message(tr("Note"),tr("error recording"));
+ recording=FALSE;;
+ break;
}
- } else { //AFMT_U8
- // 8bit unsigned
- unsigned short sound[1024], monoBuffer[1024];
- while(recording) {
- result = read(dsp, sound, 1024); // 8192
- // int j=0;
-
- // if(systemZaurus) {
+ if(useADPCM) {
+ adpcm_coder( sbuf, abuf, result/2, &encoder_state);
+ bytesWritten = ::write(wav, abuf, result/4);
+ } else {
for (int i = 0; i < result; i++) { //since Z is mono do normally
monoBuffer[i] = sound[i];
}
length+=write(wav, monoBuffer, result);
-
- // for (int i = 0; i < result; i+=2) {
- // monoBuffer[j] = (sound[i]+sound[i+1])/2;
- // j++;
- // }
- // length+=write(wav, monoBuffer, result/2);
- length += result;
- // printf("%d\r",length);
- // fflush(stdout);
- }
-
- qApp->processEvents();
}
-
- } else { // 16 bit only capabilities
-
-
- msg.sprintf("Recording format other");
- qDebug(msg);
-
- signed short sound[1024];//, monoBuffer[512];
-
- while(recording) {
-
- result = read(dsp, sound, 1024); // 8192
-
- write(wav, sound, result);
- length += result;
+ length +=bytesWritten;
if(length<0) {
-
recording=false;
perror("dev/dsp's is a lookin' messy");
QMessageBox::message("Vmemo"," Done1 recording\n"+ fileName);
}
// printf("%d\r",length);
// fflush(stdout);
qApp->processEvents();
}
// qDebug("file has length of %d lasting %d seconds",
// length, (( length / speed) / channels) / 2 );
// medialplayer states wrong length in secs
- }
+ // }
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<//
value = length+36;
lseek(wav, 4, SEEK_SET);
write(wav, &value, 4);
lseek(wav, 40, SEEK_SET);
diff --git a/core/applets/vmemo/vmemo.h b/core/applets/vmemo/vmemo.h
index 823c7b8..167af2a 100644
--- a/core/applets/vmemo/vmemo.h
+++ b/core/applets/vmemo/vmemo.h
@@ -31,17 +31,17 @@ class VMemo : public QWidget
Q_OBJECT
public:
VMemo( QWidget *parent, const char *name = NULL);
~VMemo();
QFile track;
QString fileName, errorMsg;
QLabel* msgLabel;
QTimer *t_timer;
-bool usingIcon;
+bool usingIcon, useADPCM;
public slots:
void record();
void mousePressEvent( QMouseEvent * );
void mouseReleaseEvent( QMouseEvent * );
void receive( const QCString &msg, const QByteArray &data );
bool startRecording();
void stopRecording();
void timerBreak();
diff --git a/core/applets/vmemo/vmemo.pro b/core/applets/vmemo/vmemo.pro
index f8007b6..6599b52 100644
--- a/core/applets/vmemo/vmemo.pro
+++ b/core/applets/vmemo/vmemo.pro
@@ -1,12 +1,12 @@
TEMPLATE = lib
CONFIG += qt warn_on release
-HEADERS = vmemo.h vmemoimpl.h
-SOURCES = vmemo.cpp vmemoimpl.cpp
+HEADERS = vmemo.h vmemoimpl.h adpcm.h
+SOURCES = vmemo.cpp vmemoimpl.cpp adpcm.c
TARGET = vmemoapplet
DESTDIR =$(OPIEDIR)/plugins/applets
INCLUDEPATH += $(OPIEDIR)/include
DEPENDPATH += $(OPIEDIR)/include
LIBS += -lqpe
VERSION = 1.0.0
TRANSLATIONS = ../../../i18n/de/libvmemoapplet.ts \