Files
gzz-mirror/Modules/sound/gsm_recorder.c
2026-09-14 20:19:29 -04:00

241 lines
5.9 KiB
C

/*
gsm_recorder.c
*
* Copyright (c) 2000, Ted Nelson, Tuomas Lukka and Vesa Parkkinen
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Vesa Parkkinen
*/
/**
* simple gsm recorder
*/
/****************************************************
* INCLUDES
****************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <pthread.h>
#include <gsm/gsm.h>
#include "jni.h"
#include "org_gzigzag_module_SimpleRecorder.h"
#include "gsm_def.h"
/****************************************************
* DEFINES
****************************************************/
#define DEVICE "/dev/dsp"
#define DEFAULT_DSP_SPEED 8000
#define DEFAULT_DSP_FRAG 0
#define DEFAULT_DSP_SAMPLE
#define RECS 10
#define READ_BLOCK 1280
#define BUFFER_SIZE 20 * READ_BLOCK
#define GSM_RECORDER_DEBUG 1
//#define ENCODED_SIZE 20 * READ_BLOCK
#ifndef uint
#define uint unsigned int
#endif
#ifndef ulong
#define ulong unsigned long
#endif
#ifndef DEBUG_SOUND
#define DEBUG_SOUND 0
#endif
#define DEBUG(s) if(DEBUG_SOUND)printf(s);
/****************************************************
* STRUCTS
****************************************************/
/**
* Recording
* Struct to hold infomation about recordings.
*/
typedef struct {
char *file; // file to save to
int audio; // handle to audio device
int speed;
int samplesize;
int fragsize;
int channels; // mono 1, stereo 2
ulong offset; // bytes from beginning
int format;
int stop;
} Recording;
Recording *recs[RECS];
int cur_rec = 0;
/**
*
*/
int init_recording(Recording *rec){
rec->file = "/tmp/sndscroll";
rec->audio = 0;
rec->speed = 8000;
rec->samplesize = 8;
rec->fragsize = 0; // not used at the moment
rec->channels = 1;
rec->offset = 0;
rec->stop = 0;
return 0;
}
/**
* Creates a new recording structure, and increments
* curr_rec by 1.
* @return a pointer to new Recording struvct or NULL
*/
Recording *new_recording(int *rn){
Recording *r = (Recording *) malloc(sizeof(Recording));
cur_rec++;
recs[cur_rec] = r;
*rn = cur_rec;
return r;
}
/**
* Initializes the recording device.
*/
int init_device(const char *file){
int rn = 0;
Recording *r = new_recording(&rn);
init_recording(r);
r->file = strdup(file);
r->stop = -1;
DEBUG("init device\n");
if ( (r->audio = open(DEVICE, O_RDONLY) ) < 0 ) {
perror("OPEN FAILED");
}
DEBUG("opened device\n");
if( ioctl(r->audio, SNDCTL_DSP_SAMPLESIZE, &r->samplesize) == -1){
perror("SNDCTL_DSP_SAMPLESIZE");
return -1;
}
if (ioctl(r->audio, SNDCTL_DSP_CHANNELS, &r->channels) == -1) {
perror("SNDCTL_DSP_CHANNELS");
return -1;
}
if (ioctl (r->audio, SNDCTL_DSP_SPEED, &r->speed) == -1){
perror("set speed failed");
}
DEBUG("initialized device\n");
return rn;
}
/*******************************************************************
* GET CURRENT OFFSET *
*******************************************************************/
JNIEXPORT jlong JNICALL
Java_org_gzigzag_module_SimpleRecorder_recorder_1getCurrentOffset
(JNIEnv *env, jobject obj , jint handle){
Recording *r = recs[handle];
if( r == NULL ) return 0;
return r->offset;
}
/*******************************************************************
* INIT *
*******************************************************************/
JNIEXPORT jint JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1init
(JNIEnv *env, jobject obj, jstring file, jlong offset){
int rv=0;
const char *fn = (const char *)(*env)->GetStringUTFChars(env, file, 0);
rv = init_device(fn);
(*env)->ReleaseStringUTFChars(env, file, fn);
recs[rv]->offset = offset;
return rv;
}
/*******************************************************************
* STOP *
*******************************************************************/
JNIEXPORT void JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1stop
(JNIEnv *env, jobject obj, jint handle){
Recording *r = recs[handle];
if ( r == NULL) return ;
r->stop = 1;
}
/*******************************************************************
* START *
*******************************************************************/
JNIEXPORT void JNICALL Java_org_gzigzag_module_SimpleRecorder_recorder_1start
(JNIEnv *env, jobject obj, jint handle){
int fd = 0;
char *audiobuf;
gsm gsm = gsm_create();
gsm_signal sample[160];
gsm_frame frame;
Recording *r = recs[handle];
if ((fd = open (r->file, O_WRONLY | O_CREAT, 0666)) == -1){
perror("recorder start: open failed");
return ;
}
lseek(fd, r->offset, SEEK_SET);
while ( r->stop < 1 ){
read (r->audio, sample, sizeof(sample) );
gsm_encode(gsm, sample, frame);
// write
if (write (fd, frame, sizeof(frame)) != sizeof(frame)){
perror("write failed");
//exit (-1);
return ;
}
r->offset += sizeof(frame);
}
if (fd != 1)
close (fd);
close( r->audio );
gsm_destroy(gsm);
printf("recorded\n");
}