Refactoring gear change vibration effect

This commit is contained in:
Paul Dino Jones 2023-04-08 08:52:06 +00:00
parent 5eb136312b
commit 61825e4ddf
7 changed files with 200 additions and 84 deletions

View File

@ -82,13 +82,15 @@ typedef struct
SimDevice m;
int id;
SoundType type;
VibrationEffectType effecttype;
PATestData sounddata;
PaStreamParameters outputParameters;
PaStream* stream;
}
SoundDevice;
int sounddev_update(SimDevice* this, SimData* simdata);
int sounddev_engine_update(SimDevice* this, SimData* simdata);
int sounddev_gearshift_update(SimDevice* this, SimData* simdata);
int sounddev_free(SimDevice* this);
SoundDevice* new_sound_device(DeviceSettings* ds);

View File

@ -15,8 +15,7 @@
#endif
int patestCallback(const void* inputBuffer,
int patestCallbackEngineRPM(const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
@ -36,32 +35,45 @@ int patestCallback(const void* inputBuffer,
float v = 0;
v = data->amp * sin (2 * M_PI * ((float) n) / (float) SAMPLE_RATE);
if ( data->gear_sound_data > 0 )
{
if (n>=1764)
{
n=0;
}
}
else
{
if (n>=data->table_size)
{
n=0;
}
}
*out++ = v;
*out++ = v;
}
data->n=n;
return 0;
}
int patestCallbackGearShift(const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData)
{
PATestData* data = (PATestData*)userData;
float* out = (float*)outputBuffer;
memset(out, 0, framesPerBuffer * 2 * sizeof(float));
unsigned int i;
unsigned int n;
n = data->n;
(void) inputBuffer; /* Prevent unused argument warning. */
for( i=0; i<framesPerBuffer; i++,n++ )
{
if ( data->gear_sound_data > 0 )
{
// right channel only?
// i have my butt hooked up to right channel... make this configurable?
*out++ = v;
}
else
{
*out++ = v;
*out++ = v;
data->gear_sound_data = 0;
*out++ = M_PI;
*out++ = M_PI;
*out++ = M_PI;
*out++ = M_PI;
}
}
@ -97,14 +109,28 @@ int usb_generic_shaker_init(SoundDevice* sounddevice)
sounddevice->outputParameters.suggestedLatency = Pa_GetDeviceInfo( sounddevice->outputParameters.device )->defaultLowOutputLatency;
sounddevice->outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream( &sounddevice->stream,
NULL, /* No input. */
&sounddevice->outputParameters, /* As above. */
SAMPLE_RATE,
440, /* Frames per buffer. */
paClipOff, /* No out of range samples expected. */
patestCallback,
&sounddevice->sounddata );
if (sounddevice->effecttype == SOUNDEFFECT_GEARSHIFT)
{
err = Pa_OpenStream( &sounddevice->stream,
NULL, /* No input. */
&sounddevice->outputParameters, /* As above. */
SAMPLE_RATE,
440, /* Frames per buffer. */
paClipOff, /* No out of range samples expected. */
patestCallbackGearShift,
&sounddevice->sounddata );
}
else
{
err = Pa_OpenStream( &sounddevice->stream,
NULL, /* No input. */
&sounddevice->outputParameters, /* As above. */
SAMPLE_RATE,
440, /* Frames per buffer. */
paClipOff, /* No out of range samples expected. */
patestCallbackEngineRPM,
&sounddevice->sounddata );
}
if( err != paNoError )
{
goto error;
@ -121,8 +147,5 @@ int usb_generic_shaker_init(SoundDevice* sounddevice)
error:
Pa_Terminate();
//fprintf( stderr, "An error occured while using the portaudio stream\n" );
//fprintf( stderr, "Error number: %d\n", err );
//fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@ -8,16 +8,22 @@
#include "../helper/parameters.h"
#include "../slog/slog.h"
int sounddev_update(SimDevice* this, SimData* simdata)
// we could make a vtable for these different effects too
int sounddev_engine_update(SimDevice* this, SimData* simdata)
{
SoundDevice* sounddevice = (void *) this->derived;
sounddevice->sounddata.table_size = 44100/(simdata->rpms/60);
}
int sounddev_gearshift_update(SimDevice* this, SimData* simdata)
{
SoundDevice* sounddevice = (void *) this->derived;
sounddevice->sounddata.gear_sound_data = 0;
if (sounddevice->sounddata.last_gear != simdata->gear)
{
sounddevice->sounddata.gear_sound_data = sounddevice->sounddata.amp;
sounddevice->sounddata.gear_sound_data = 3.14;
}
sounddevice->sounddata.last_gear = simdata->gear;
}
@ -47,7 +53,8 @@ int sounddev_init(SoundDevice* sounddevice)
usb_generic_shaker_init(sounddevice);
}
static const vtable sound_simdevice_vtable = { &sounddev_update, &sounddev_free };
static const vtable engine_sound_simdevice_vtable = { &sounddev_engine_update, &sounddev_free };
static const vtable gear_sound_simdevice_vtable = { &sounddev_gearshift_update, &sounddev_free };
SoundDevice* new_sound_device(DeviceSettings* ds) {
@ -56,9 +63,28 @@ SoundDevice* new_sound_device(DeviceSettings* ds) {
this->m.update = &update;
this->m.free = &simdevfree;
this->m.derived = this;
this->m.vtable = &sound_simdevice_vtable;
sounddev_init(this);
slogt("Attempting to configure sound device with subtype: %i", ds->dev_subtype);
switch (ds->dev_subtype) {
case (SIMDEVTYPE_ENGINESOUND):
this->effecttype = SOUNDEFFECT_ENGINERPM;
this->m.vtable = &engine_sound_simdevice_vtable;
slogi("Initializing sound device for engine vibrations.");
break;
case (SIMDEVTYPE_GEARSOUND):
this->effecttype = SOUNDEFFECT_GEARSHIFT;
this->m.vtable = &gear_sound_simdevice_vtable;
slogi("Initializing sound device for gear shift vibrations.");
break;
}
int error = sounddev_init(this);
if (error != 0)
{
free(this);
return NULL;
}
return this;
}

View File

@ -10,6 +10,13 @@ typedef enum
}
SoundType;
typedef enum
{
SOUNDEFFECT_ENGINERPM = 0,
SOUNDEFFECT_GEARSHIFT = 1
}
VibrationEffectType;
#define MAX_TABLE_SIZE (6000)
typedef struct
{

View File

@ -242,7 +242,7 @@ int looper(SimDevice* devices, int numdevices, Simulator simulator)
int tester(SimDevice* devices, int numdevices)
{
slogi("preparing game loop with %i devices...", numdevices);
slogi("preparing test with %i devices...", numdevices);
SimData* simdata = malloc(sizeof(SimData));
struct termios newsettings, canonicalmode;
@ -254,7 +254,10 @@ int tester(SimDevice* devices, int numdevices)
tcsetattr(0, TCSANOW, &newsettings);
fprintf(stdout, "\n");
simdata->gear = 0;
simdata->rpms = 100;
simdata->maxrpm = 8000;
sleep(3);
fprintf(stdout, "Setting rpms to 1000\n");
simdata->rpms = 1000;
@ -264,6 +267,30 @@ int tester(SimDevice* devices, int numdevices)
}
sleep(3);
fprintf(stdout, "Shifting into first gear\n");
simdata->gear = 1;
for (int x = 0; x < numdevices; x++)
{
devices[x].update(&devices[x], simdata);
}
sleep(3);
fprintf(stdout, "Shifting into second gear\n");
simdata->gear = 2;
for (int x = 0; x < numdevices; x++)
{
devices[x].update(&devices[x], simdata);
}
sleep(3);
fprintf(stdout, "Shifting into third gear\n");
simdata->gear = 3;
for (int x = 0; x < numdevices; x++)
{
devices[x].update(&devices[x], simdata);
}
sleep(3);
fprintf(stdout, "Setting rpms to 2000\n");
simdata->rpms = 2000;
for (int x = 0; x < numdevices; x++)
@ -280,6 +307,14 @@ int tester(SimDevice* devices, int numdevices)
}
sleep(3);
fprintf(stdout, "Shifting into fourth gear\n");
simdata->gear = 4;
for (int x = 0; x < numdevices; x++)
{
devices[x].update(&devices[x], simdata);
}
sleep(3);
fprintf(stdout, "Setting rpms to 8000\n");
simdata->rpms = 8000;
for (int x = 0; x < numdevices; x++)

View File

@ -2,6 +2,7 @@
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include <libxml/parser.h>
#include <libxml/xmlreader.h>
@ -11,21 +12,32 @@
#include "../slog/slog.h"
int strcicmp(char const *a, char const *b)
{
for (;; a++, b++) {
int d = tolower((unsigned char)*a) - tolower((unsigned char)*b);
if (d != 0 || !*a)
return d;
}
}
int strtogame(const char* game, MonocoqueSettings* ms)
{
slogd("Checking for %s in list of supported simulators.", game);
if (strcmp(game, "ac") == 0)
if (strcicmp(game, "ac") == 0)
{
slogd("Setting simulator to Assetto Corsa");
ms->sim_name = SIMULATOR_ASSETTO_CORSA;
}
else if (strcmp(game, "rf2") == 0)
else if (strcicmp(game, "rf2") == 0)
{
slogd("Setting simulator to RFactor 2");
ms->sim_name = SIMULATOR_RFACTOR2;
}
else
if (strcmp(game, "test") == 0)
if (strcicmp(game, "test") == 0)
{
slogd("Setting simulator to Test Data");
ms->sim_name = SIMULATOR_MONOCOQUE_TEST;
@ -38,22 +50,63 @@ int strtogame(const char* game, MonocoqueSettings* ms)
return MONOCOQUE_ERROR_NONE;
}
int strtodev(const char* device_type, DeviceSettings* ds)
int strtodevsubtype(const char* device_subtype, DeviceSettings* ds, int simdev)
{
ds->is_valid = false;
if (strcmp(device_type, "USB") == 0)
ds->dev_subtype = SIMDEVTYPE_UNKNOWN;
switch (simdev) {
case SIMDEV_USB:
if (strcicmp(device_subtype, "Tachometer") == 0)
{
ds->dev_subtype = SIMDEVTYPE_TACHOMETER;
break;
}
case SIMDEV_SERIAL:
if (strcicmp(device_subtype, "ShiftLights") == 0)
{
ds->dev_subtype = SIMDEVTYPE_SHIFTLIGHTS;
break;
}
case SIMDEV_SOUND:
if (strcicmp(device_subtype, "Engine") == 0)
{
ds->dev_subtype = SIMDEVTYPE_ENGINESOUND;
break;
}
if (strcicmp(device_subtype, "Gear") == 0)
{
ds->dev_subtype = SIMDEVTYPE_GEARSOUND;
break;
}
default:
ds->is_valid = false;
slogw("%s does not appear to be a valid device sub type, but attempting to continue with other devices", device_subtype);
return MONOCOQUE_ERROR_INVALID_DEV;
}
ds->is_valid = true;
return MONOCOQUE_ERROR_NONE;
}
int strtodev(const char* device_type, const char* device_subtype, DeviceSettings* ds)
{
ds->is_valid = false;
if (strcicmp(device_type, "USB") == 0)
{
ds->dev_type = SIMDEV_USB;
strtodevsubtype(device_subtype, ds, SIMDEV_USB);
}
else
if (strcmp(device_type, "Sound") == 0)
if (strcicmp(device_type, "Sound") == 0)
{
ds->dev_type = SIMDEV_SOUND;
strtodevsubtype(device_subtype, ds, SIMDEV_SOUND);
}
else
if (strcmp(device_type, "Serial") == 0)
if (strcicmp(device_type, "Serial") == 0)
{
ds->dev_type = SIMDEV_SERIAL;
strtodevsubtype(device_subtype, ds, SIMDEV_SERIAL);
}
else
{
@ -65,33 +118,6 @@ int strtodev(const char* device_type, DeviceSettings* ds)
return MONOCOQUE_ERROR_NONE;
}
int strtodevtype(const char* device_subtype, DeviceSettings* ds)
{
ds->is_valid = false;
if (strcmp(device_subtype, "Tachometer") == 0)
{
ds->dev_subtype = SIMDEVTYPE_TACHOMETER;
}
else
if (strcmp(device_subtype, "ShiftLights") == 0)
{
ds->dev_subtype = SIMDEVTYPE_SHIFTLIGHTS;
}
else
if (strcmp(device_subtype, "Shaker") == 0)
{
ds->dev_subtype = SIMDEVTYPE_SHAKER;
}
else
{
ds->is_valid = false;
slogi("%s does not appear to be a valid device sub type, but attempting to continue with other devices", device_subtype);
return MONOCOQUE_ERROR_INVALID_DEV;
}
ds->is_valid = true;
return MONOCOQUE_ERROR_NONE;
}
int loadtachconfig(const char* config_file, DeviceSettings* ds)
{
@ -131,7 +157,7 @@ int loadtachconfig(const char* config_file, DeviceSettings* ds)
{
slogt("Xml Element name %s", cursubsubnode->name);
}
if (strcmp(cursubsubnode->name, "SettingsItem") == 0)
if (strcicmp(cursubsubnode->name, "SettingsItem") == 0)
{
arraysize++;
}
@ -153,13 +179,13 @@ int loadtachconfig(const char* config_file, DeviceSettings* ds)
{
for (cursubsubsubnode = cursubsubnode->children; cursubsubsubnode; cursubsubsubnode = cursubsubsubnode->next)
{
if (strcmp(cursubsubsubnode->name, "Value") == 0)
if (strcicmp(cursubsubsubnode->name, "Value") == 0)
{
xmlChar* a = xmlNodeGetContent(cursubsubsubnode);
rpms_array[i] = strtol((char*) a, &buf, 10);
xmlFree(a);
}
if (strcmp(cursubsubsubnode->name, "TimeValue") == 0)
if (strcicmp(cursubsubsubnode->name, "TimeValue") == 0)
{
xmlChar* a = xmlNodeGetContent(cursubsubsubnode);
pulses_array[i] = strtol((char*) a, &buf, 10);
@ -199,17 +225,13 @@ int devsetup(const char* device_type, const char* device_subtype, const char* co
int error = MONOCOQUE_ERROR_NONE;
slogi("Called device setup with %s %s %s", device_type, device_subtype, config_file);
ds->dev_type = SIMDEV_UNKNOWN;
ds->dev_subtype = SIMDEVTYPE_UNKNOWN;
error = strtodev(device_type, ds);
if (error != MONOCOQUE_ERROR_NONE)
{
return error;
}
error = strtodevtype(device_subtype, ds);
error = strtodev(device_type, device_subtype, ds);
if (error != MONOCOQUE_ERROR_NONE)
{
return error;
}
if (ms->program_action == A_PLAY)
{
error = loadconfig(config_file, ds);

View File

@ -21,8 +21,9 @@ typedef enum
{
SIMDEVTYPE_UNKNOWN = 0,
SIMDEVTYPE_TACHOMETER = 1,
SIMDEVTYPE_SHAKER = 2,
SIMDEVTYPE_SHIFTLIGHTS = 3
SIMDEVTYPE_SHIFTLIGHTS = 2,
SIMDEVTYPE_ENGINESOUND = 3,
SIMDEVTYPE_GEARSOUND = 4
}
DeviceSubType;