mirror of
https://github.com/thestk/stk
synced 2026-01-13 13:01:52 +00:00
Version 2.01
This commit is contained in:
committed by
Stephen Sinclair
parent
6485746ee9
commit
ea749b71d2
214
MatWvOut.cpp
Normal file
214
MatWvOut.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
/*******************************************/
|
||||
/* Matlab MAT File Output Class, */
|
||||
/* by Gary P. Scavone, 1998. */
|
||||
/* This object creates a Matlab MAT-file */
|
||||
/* structure and fills it with buffers of */
|
||||
/* samples (doubles). */
|
||||
/* */
|
||||
/* The Matlab MAT-file format is not */
|
||||
/* available to the general public. I */
|
||||
/* spent several days reverse-engineering */
|
||||
/* the file format to create this class. */
|
||||
/* I couldn't figure out what a few of */
|
||||
/* the header fields correspond to, but */
|
||||
/* for the purposes of STK, this */
|
||||
/* shouldn't create any problems. */
|
||||
/*******************************************/
|
||||
|
||||
#include "MatWvOut.h"
|
||||
|
||||
/******** Matlab Matfile Header Struct *******/
|
||||
struct matheaderform {
|
||||
char heading[124];
|
||||
short a[2];
|
||||
long b[10];
|
||||
/* There's more, but it's of variable length */
|
||||
};
|
||||
|
||||
FILE *openMatFile(int chans,char *fileName) {
|
||||
struct matheaderform hdr;
|
||||
FILE *fd;
|
||||
char tempName[128];
|
||||
int i, namelen;
|
||||
long longtmp, headsize;
|
||||
|
||||
strcpy(hdr.heading,"MATLAB 5.0 MAT-file, Generated by STK98. This file format was hacked by Gary P. Scavone, CCRMA, Stanford University, 1998.");
|
||||
|
||||
for (i=strlen(hdr.heading);i<124;i++) hdr.heading[i] = ' ';
|
||||
|
||||
hdr.a[0] = (short) 256;
|
||||
hdr.a[1] = (short) 'M';
|
||||
hdr.a[1] <<= 8;
|
||||
hdr.a[1] += 'I';
|
||||
hdr.b[0] = (long) 14;
|
||||
hdr.b[1] = (long) 0; /* Size of file after this point to end (in bytes) */
|
||||
hdr.b[2] = (long) 6;
|
||||
hdr.b[3] = (long) 8;
|
||||
hdr.b[4] = (long) 6;
|
||||
hdr.b[5] = (long) 0;
|
||||
hdr.b[6] = (long) 5;
|
||||
hdr.b[7] = (long) 8;
|
||||
hdr.b[8] = (long) chans; /* This is the number of rows */
|
||||
hdr.b[9] = (long) 0; /* This is the number of columns */
|
||||
|
||||
strcpy(tempName,fileName);
|
||||
strcat(tempName,".mat");
|
||||
|
||||
fd = fopen(tempName,"w+b");
|
||||
if (!fd) {
|
||||
printf("Couldn't create matfile %s !!!!!!!!\n",fileName);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printf("Creating matfile %s.\n", tempName);
|
||||
fwrite(&hdr,sizeof(char),168,fd); /* Write the fixed portion of the header */
|
||||
|
||||
/* The next 4 bytes can be viewed as two shorts, but they are byteswapped
|
||||
as a long. The first short value seems to always be one; the second
|
||||
short will be the length of the variable name IF IT IS <= 4; if the
|
||||
variable name length is >4, this short is zero and the length is put
|
||||
in the next 4 bytes. The variable name length is limited to 31
|
||||
characters (32 with a '\n'). The actual variable name then follows.
|
||||
The variable name is "zero-padded" out to the following minimum
|
||||
lengths (in bits): 4, 8, 16, 24, 32.
|
||||
*/
|
||||
namelen = strlen(fileName);
|
||||
if (namelen > 31) { /* Check length of variable name (file name) */
|
||||
fprintf(stderr, "File name too long ... should be 31 characters or less.\n");
|
||||
fclose(fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (namelen > 4) {
|
||||
longtmp = 1;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
fwrite(&namelen,sizeof(long),1,fd);
|
||||
headsize = 44 + namelen;
|
||||
} else {
|
||||
longtmp = namelen;
|
||||
longtmp <<= 16;
|
||||
longtmp += 1;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
headsize = 40 + namelen;
|
||||
}
|
||||
|
||||
fwrite(fileName,sizeof(char),namelen,fd); /* Write the variable (file) name */
|
||||
if (namelen < 5)
|
||||
longtmp = 4 - namelen;
|
||||
else if (namelen < 9)
|
||||
longtmp = 8 - namelen;
|
||||
else if (namelen < 17)
|
||||
longtmp = 16 - namelen;
|
||||
else if (namelen < 25)
|
||||
longtmp = 24 - namelen;
|
||||
else longtmp = 32 - namelen;
|
||||
|
||||
headsize += longtmp + 8; /* Add length (8) of following bytes */
|
||||
fseek(fd,longtmp,SEEK_CUR);
|
||||
|
||||
longtmp = 9;
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
longtmp = 0; /* Size of data in bytes (8 per sample) */
|
||||
fwrite(&longtmp,sizeof(long),1,fd);
|
||||
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fwrite(&headsize,sizeof(long),1,fd); /* Write header size ... will update at end */
|
||||
fseek(fd,0,SEEK_END);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
MatWvOut :: MatWvOut(char *fileName)
|
||||
{
|
||||
chans = 1;
|
||||
pan = 0.5;
|
||||
fd = openMatFile(chans,fileName);
|
||||
counter = 0;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
MatWvOut :: MatWvOut(int channels, char *fileName)
|
||||
{
|
||||
chans = channels;
|
||||
pan = 0.5;
|
||||
fd = openMatFile(chans,fileName);
|
||||
counter = 0;
|
||||
totalCount = 0;
|
||||
}
|
||||
|
||||
MatWvOut :: ~MatWvOut()
|
||||
{
|
||||
double temp;
|
||||
long headsize, temp1;
|
||||
|
||||
fwrite(data,sizeof(double),counter,fd);
|
||||
temp = (double) totalCount * ONE_OVER_SRATE;
|
||||
printf("%f Seconds Computed\n",temp);
|
||||
fseek(fd,164,SEEK_SET);
|
||||
fwrite(&totalCount,sizeof(long),1,fd); /* Write number of columns */
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fread(&headsize,sizeof(long),1,fd);
|
||||
temp1 = headsize;
|
||||
headsize += (long) (totalCount * 8 * 2);
|
||||
fseek(fd,132,SEEK_SET);
|
||||
fwrite(&headsize,sizeof(long),1,fd); /* Write file size (minus some header info) */
|
||||
fseek(fd,temp1+128,SEEK_SET);
|
||||
temp1 = totalCount * 8 * 2;
|
||||
fwrite(&temp1,sizeof(long),1,fd); /* Write data size (in bytes) */
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
long MatWvOut :: getCounter()
|
||||
{
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
MY_FLOAT MatWvOut :: getTime()
|
||||
{
|
||||
return (MY_FLOAT) totalCount * ONE_OVER_SRATE;
|
||||
}
|
||||
|
||||
void MatWvOut :: tick(MY_FLOAT sample)
|
||||
{
|
||||
if (chans==1) {
|
||||
data[counter++] = (double) (sample);
|
||||
}
|
||||
else {
|
||||
data[counter++] = (double) (sample * (1.0 - pan));
|
||||
data[counter++] = (double) (sample * pan);
|
||||
}
|
||||
totalCount += 1;
|
||||
if (counter == MAT_BUFFER_SIZE) {
|
||||
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MatWvOut :: tick(MY_FLOAT lsamp, MY_FLOAT rsamp)
|
||||
{
|
||||
if (chans==1) {
|
||||
data[counter++] = (double) (lsamp + rsamp);
|
||||
}
|
||||
else {
|
||||
data[counter++] = (double) (lsamp);
|
||||
data[counter++] = (double) (rsamp);
|
||||
}
|
||||
totalCount += 1;
|
||||
if (counter == MAT_BUFFER_SIZE) {
|
||||
fwrite(data,sizeof(double),MAT_BUFFER_SIZE,fd);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MatWvOut :: setMonoPan(MY_FLOAT aPan)
|
||||
{
|
||||
pan = aPan;
|
||||
if (aPan < 0.0) {
|
||||
pan = 0.0;
|
||||
printf("Pan < 0.0, correcting to 0.0\n");
|
||||
}
|
||||
if (aPan > 1.0) {
|
||||
pan = 1.0;
|
||||
printf("Pan > 1.0, correcting to 1.0\n");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user