예제 #1
0
//-----------------------------------------------------------------------------
// Makes a single frame of spheremap
//-----------------------------------------------------------------------------
void CVTFTexture::ComputeSpheremapFrame( unsigned char **ppCubeFaces, unsigned char *pSpheremap, LookDir_t lookDir )
{
	SphereCalc_t sphere;
	CalcInit( &sphere, m_nWidth, ppCubeFaces, lookDir );
	int offset = 0;
	for ( int y = 0; y < m_nHeight; y++ )
	{
		for ( int x = 0; x < m_nWidth; x++ )
		{
			int r = 0, g = 0, b = 0, a = 0;
			float u = (float)x - m_nWidth * 0.5f;
			float v = m_nHeight * 0.5f - (float)y;

			CalcSphereColor( &sphere, u, v );
			r += sphere.m_pColor[0];
			g += sphere.m_pColor[1];
			b += sphere.m_pColor[2];
			a += sphere.m_pColor[3];

			CalcSphereColor( &sphere, u + 0.25, v );
			r += sphere.m_pColor[0];
			g += sphere.m_pColor[1];
			b += sphere.m_pColor[2];
			a += sphere.m_pColor[3];

			v += 0.25;
			CalcSphereColor( &sphere, u + 0.25, v );
			r += sphere.m_pColor[0];
			g += sphere.m_pColor[1];
			b += sphere.m_pColor[2];
			a += sphere.m_pColor[3];

			CalcSphereColor( &sphere, u, v );
			r += sphere.m_pColor[0];
			g += sphere.m_pColor[1];
			b += sphere.m_pColor[2];
			a += sphere.m_pColor[3];

			pSpheremap[ offset + 0 ] = r >> 2;
			pSpheremap[ offset + 1 ] = g >> 2;
			pSpheremap[ offset + 2 ] = b >> 2;
			pSpheremap[ offset + 3 ] = a >> 2;
			offset += 4;
		}
	}
}
예제 #2
0
int OmConvertRunConvert(omconvert_settings_t *settings, calc_t *calc)
{
	int retVal = EXIT_OK;
	omdata_t omdata = { 0 };
	om_convert_arrangement_t arrangement = { 0 };

	// Output information file
	FILE *infofp = NULL;
	if (settings->infoFilename != NULL)
	{
		infofp = fopen(settings->infoFilename, "wt");
		if (infofp == NULL)
		{
			fprintf(stderr, "ERROR: Cannot open output information file: %s\n", settings->infoFilename);
			return EXIT_CANTCREAT;
		}
	}
		
	// Load input data
	if (!OmDataLoad(&omdata, settings->filename))
	{
		const char *msg = "ERROR: Problem loading file.\n";
		fprintf(stderr, msg);
		fprintf(stdout, msg);
		return EXIT_DATAERR;
	}
	fprintf(stderr, "Data loaded!\n");

	OmDataDump(&omdata);

	// For each session:
	omdata_session_t *session;
	int sessionCount = 0;
	for (session = omdata.firstSession; session != NULL; session = session->sessionNext)
	{
		sessionCount++;
		fprintf(stderr, "=== SESSION %d ===\n", sessionCount);

		if (sessionCount > 1)
		{
			fprintf(stderr, "NOTE: Skipping session %d...\n", sessionCount);
			continue;
		}

		// Find a configuration
		OmConvertFindArrangement(&arrangement, settings, &omdata, session, defaultChannelPriority);

		// Calibration configuration
		omcalibrate_config_t calibrateConfig = { 0 };
		OmCalibrateConfigInit(&calibrateConfig);
		calibrateConfig.stationaryTime = settings->stationaryTime; // 10.0;
		calibrateConfig.stationaryRepeated = settings->repeatedStationary;

		// Start a player
		om_convert_player_t player = { 0 };
		OmConvertPlayerInitialize(&player, &arrangement, settings->sampleRate, settings->interpolate);					// Initialize here for find stationary points

		// Initialize calibration
		omcalibrate_calibration_t calibration;
		OmCalibrateInit(&calibration);

		if (settings->calibrate)
		{
			// Find stationary points
			omcalibrate_stationary_points_t *stationaryPoints;
			fprintf(stderr, "Finding stationary points...\n");
			stationaryPoints = OmCalibrateFindStationaryPoints(&calibrateConfig, &player);		// Player already initialized
			fprintf(stderr, "Found stationary points: %d\n", stationaryPoints->numValues);

			// Dump no calibration
			OmCalibrateDump(&calibration, stationaryPoints, 0);

			// Auto-calibrate
			fprintf(stderr, "Auto-calibrating...\n");
			int calibrationResult = OmCalibrateFindAutoCalibration(&calibrateConfig, stationaryPoints, &calibration);
			OmCalibrateDump(&calibration, stationaryPoints, 1);
			if (calibrationResult < 0)
			{
				fprintf(stderr, "Auto-calibration: using identity calibration...\n");
				int ec = calibration.errorCode;		// Copy error code
				int na = calibration.numAxes;		// ...and num-axes
				OmCalibrateInit(&calibration);
				calibration.errorCode = ec;			// Copy error code to identity calibration
				calibration.numAxes = na;			// ...and num-axes
			}

			// Free stationary points
			OmCalibrateFreeStationaryPoints(stationaryPoints);

		}

		// Output range scalings 
		int outputAccelRange = 8;								// TODO: Possibly allow for +/- 16 outputs (currently always +/-8g -> 16-bit signed)?
		if (outputAccelRange < 8) { outputAccelRange = 8; }		// Minimum of +/-2, +/-4, +/-8 all get output coded as +/-8
		int outputAccelScale = 65536 / (2 * outputAccelRange);

		int outputChannels = arrangement.numChannels + 1;
		int outputRate = (int)(player.sampleRate + 0.5);
		int outputSamples = player.numSamples;

		// Metadata - [Artist�"IART" WAV chunk] Data about the device that made the recording
		char artist[WAV_META_LENGTH] = { 0 };
		sprintf(artist,
			"Id: %u\n"
			"Device: %s\n"
			"Revision: %d\n"
			"Firmware: %d",
			omdata.metadata.deviceId,
			omdata.metadata.deviceTypeString,
			omdata.metadata.deviceVersion,
			omdata.metadata.firmwareVer
			);

		// Metadata - [Title�"INAM" WAV chunk] Data about the recording configuration
		char name[WAV_META_LENGTH] = { 0 };
		sprintf(name,
			"Session: %u\n"
			"Start: %s\n"
			"Stop: %s\n"
			"Config-A: %d,%d\n"
			"Metadata: %s",
			(unsigned int)omdata.metadata.sessionId,
			TimeString(omdata.metadata.recordingStart),
			TimeString(omdata.metadata.recordingStop),
			omdata.metadata.configAccel.frequency, omdata.metadata.configAccel.sensitivity,
			omdata.metadata.metadata
			);

		// Metadata - [Creation�date�"ICRD"�WAV�chunk] - Specify�the�time of the first sample (also in the comment for Matlab)
		char datetime[WAV_META_LENGTH] = { 0 };
		sprintf(datetime, "%s", TimeString(arrangement.startTime));

		// Metadata - [Comment�"ICMT" WAV chunk] Data about this file representation
		char comment[WAV_META_LENGTH] = { 0 };
		sprintf(comment,
			"Time: %s\n"
			"Channel-1: Accel-X\n"
			"Scale-1: %d\n"
			"Channel-2: Accel-Y\n"
			"Scale-2: %d\n"
			"Channel-3: Accel-Z\n"
			"Scale-3: %d\n"
			"Channel-4: Aux",
			TimeString(arrangement.startTime),
			outputAccelRange,
			outputAccelRange,
			outputAccelRange
			);

		// Create output WAV file
		FILE *ofp = NULL;
		if (settings->outFilename != NULL && strlen(settings->outFilename) > 0)
		{
			fprintf(stderr, "Generating WAV file: %s\n", settings->outFilename);
			ofp = fopen(settings->outFilename, "wb");
			if (ofp == NULL)
			{
				fprintf(stderr, "Cannot open output WAV file: %s\n", settings->outFilename);
				retVal = EXIT_CANTCREAT;
				break;
			}

			WavInfo wavInfo = { 0 };
			wavInfo.bytesPerChannel = 2;
			wavInfo.chans = outputChannels;
			wavInfo.freq = outputRate;
			wavInfo.numSamples = outputSamples;
			wavInfo.infoArtist = artist;
			wavInfo.infoName = name;
			wavInfo.infoDate = datetime;
			wavInfo.infoComment = comment;

			// Try to start the data at 1k offset (create a dummy 'JUNK' header)
			wavInfo.offset = 1024;

			if (WavWrite(&wavInfo, ofp) <= 0)
			{
				fprintf(stderr, "ERROR: Problem writing WAV file.\n");
				retVal = EXIT_IOERR;
				break;
			}
		}


		// Re-start the player
		OmConvertPlayerInitialize(&player, &arrangement, settings->sampleRate, settings->interpolate);

		int outputOk = CalcInit(calc, player.sampleRate, player.arrangement->startTime);		// Whether any processing outputs are used

		// Calculate each output sample between the start/end time of session
		if (!outputOk && ofp == NULL)
		{
			fprintf(stderr, "ERROR: No output.\n");
			retVal = EXIT_CONFIG;
			break;
		}
		else
		{

			// Write other information to info file
			if (infofp != NULL)
			{
				fprintf(infofp, ":\n");
				fprintf(infofp, "::: Data about the conversion process\n");
				fprintf(infofp, "Result-file-version: %d\n", 1);
				fprintf(infofp, "Convert-version: %d\n", CONVERT_VERSION);
				fprintf(infofp, "Processed: %s\n", TimeString(TimeNow()));
				fprintf(infofp, "File-input: %s\n", settings->filename);
				fprintf(infofp, "File-output: %s\n", settings->outFilename);
				fprintf(infofp, "Results-output: %s\n", settings->infoFilename);
				fprintf(infofp, "Auto-calibration: %d\n", settings->calibrate);
				fprintf(infofp, "Calibration-Result: %d\n", calibration.errorCode);
				fprintf(infofp, "Calibration: %.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f,%.10f\n",
					calibration.scale[0], calibration.scale[1], calibration.scale[2],
					calibration.offset[0], calibration.offset[1], calibration.offset[2],
					calibration.tempOffset[0], calibration.tempOffset[1], calibration.tempOffset[2],
					calibration.referenceTemperature);
				fprintf(infofp, "Input-sectors-total: %d\n", omdata.statsTotalSectors);
				fprintf(infofp, "Input-sectors-data: %d\n", omdata.statsDataSectors);
				fprintf(infofp, "Input-sectors-bad: %d\n", omdata.statsBadSectors);
				fprintf(infofp, "Output-rate: %d\n", outputRate);
				fprintf(infofp, "Output-channels: %d\n", outputChannels);
				fprintf(infofp, "Output-duration: %f\n", (float)outputSamples / outputRate);
				fprintf(infofp, "Output-samples: %d\n", outputSamples);
				fprintf(infofp, ":\n");
				fprintf(infofp, "::: Data about the device that made the recording\n");
				fprintf(infofp, "%s\n", artist);
				fprintf(infofp, ":\n");
				fprintf(infofp, "::: Data about the recording itself\n");
				fprintf(infofp, "%s\n", name);
				fprintf(infofp, ":\n");
				fprintf(infofp, "::: Data about this file representation\n");
				fprintf(infofp, "%s\n", comment);
			}

			signed short values[OMDATA_MAX_CHANNELS + 1];
			int sample;
			for (sample = 0; sample < outputSamples; sample++)
			{
				OmConvertPlayerSeek(&player, sample);

				// Convert to integers
				int c;
				double temp = player.temp;
				char clipped = player.clipped;

				double accel[OMCALIBRATE_AXES];
				for (c = 0; c < player.arrangement->numChannels; c++)
				{
					double interpVal = player.values[c];
					double v = player.scale[c] * interpVal;

					// Apply calibration
					if (c < OMCALIBRATE_AXES)
					{
						// Rescaling is:  v = (v + offset) * scale + (temp - referenceTemperature) * tempOffset
						v = (v + calibration.offset[c]) * calibration.scale[c] + (temp - calibration.referenceTemperature) * calibration.tempOffset[c];
					}

					if (c < OMCALIBRATE_AXES)
					{
						accel[c] = v;
					}

					// Output range scaled
					double ov = v * outputAccelScale;

					// Saturate
					if (ov < -32768.0) { ov = -32768.0; clipped = 1; }
					if (ov > 32767.0) { ov = 32767.0; clipped = 1; }

					// Save
					values[c] = (signed short)(ov);
				}


				// Auxilliary channel
				uint16_t aux = 0;
				if (!player.valid) { aux |= WAV_AUX_UNAVAILABLE; }
				if (clipped) { aux |= WAV_AUX_CLIPPING; }

				int cycle = sample % (int)player.sampleRate;
				if (cycle == 0) { aux |= WAV_AUX_SENSOR_BATTERY | (player.aux[0] & 0x3ff); }
				if (cycle == 1) { aux |= WAV_AUX_SENSOR_LIGHT | (player.aux[1] & 0x3ff); }
				if (cycle == 2) { aux |= WAV_AUX_SENSOR_TEMPERATURE | (player.aux[2] & 0x3ff); }

				//player.ettings.auxChannel

				values[player.arrangement->numChannels] = aux;
				if (!CalcAddValue(calc, accel, 0.0, player.valid ? true : false))
				{
					fprintf(stderr, "ERROR: Problem writing calculations.\n");
					retVal = EXIT_IOERR;
					break;
				}

#if 0
				// TEMPORARY: Write SVM (before filtering) to fourth channel
				double outSvm = svm * 4096.0;
				if (outSvm < -32768.0) { outSvm = -32768.0; }
				if (outSvm > 32767.0) { outSvm = 32767.0; }
				values[player.arrangement->numChannels] = (signed short)outSvm;
#endif

				// Output
				//for (c = 0; c < numChannels + 1; c++) { printf("%s%d", (c > 0) ? "," : "", values[c]); }
				//printf("\n");

				if (ofp != NULL)
				{
					int bytesToWrite = sizeof(int16_t) * (arrangement.numChannels + 1);
					static unsigned char cache[1024 * 1024];		// TODO: Don't do this - not thread safe
					static int cachePosition = 0;					// ...or this...

					memcpy(cache + cachePosition, values, bytesToWrite);
					cachePosition += bytesToWrite;
					if (cachePosition + bytesToWrite >= sizeof(cache) || sample + 1 >= outputSamples)
					{
						if (fwrite(cache, 1, cachePosition, ofp) != cachePosition)
						{
							fprintf(stderr, "ERROR: Problem writing output.\n");
							retVal = EXIT_IOERR;
							break;
						}
						cachePosition = 0;
						fprintf(stderr, ".");
					}
				}
			}

		}

		if (ofp != NULL) { fclose(ofp); }

		CalcClose(calc);

		fprintf(stderr, "\n");
		fprintf(stderr, "Finished.\n");

	}

	OmDataFree(&omdata);

	if (sessionCount < 1)
	{
		fprintf(stderr, "ERROR: No sessions to write.\n");
		retVal = EXIT_DATAERR;
	}

	if (infofp != NULL)
	{
		// Write other information to info file
		fprintf(infofp, ":\n");
		fprintf(infofp, "::: Data about the final state\n");
		fprintf(infofp, "Exit: %d\n", retVal);

		fclose(infofp);
		infofp = NULL;
	}

	return retVal;
}
예제 #3
0
int OmConvertRunWav(omconvert_settings_t *settings, calc_t *calc)
{
	int retVal = EXIT_OK;
	int i;
	FILE *fp;
	WavInfo wavInfo = { 0 };
	char infoArtist[WAV_META_LENGTH] = { 0 };
	char infoName[WAV_META_LENGTH] = { 0 };
	char infoComment[WAV_META_LENGTH] = { 0 };
	char infoDate[WAV_META_LENGTH] = { 0 };
	double scale[10] = { 8.0 / 32768.0, 8.0 / 32768.0, 8.0 / 32768.0 };

	// Check config.
	if (settings->outFilename != NULL) { fprintf(stderr, "ERROR: Cannot output to WAV when input is WAV.\n"); return EXIT_CONFIG; }
	if (settings->infoFilename != NULL) { fprintf(stderr, "ERROR: Cannot output to info file when input is WAV.\n"); return EXIT_CONFIG; }

	fp = fopen(settings->filename, "rb");
	if (fp == NULL) { fprintf(stderr, "ERROR: Cannot open WAV file.\n"); return EXIT_NOINPUT; }

	wavInfo.infoArtist = infoArtist;
	wavInfo.infoName = infoName;
	wavInfo.infoComment = infoComment;
	wavInfo.infoDate = infoDate;

	if (!WavRead(&wavInfo, fp)) { fprintf(stderr, "ERROR: Problem reading WAV file format.\n"); fclose(fp); return EXIT_DATAERR; }
	if (wavInfo.bytesPerChannel != 2) { fprintf(stderr, "ERROR: WAV file format not supported (%d bytes/channel, expected 2).\n", wavInfo.bytesPerChannel); fclose(fp); return EXIT_DATAERR; }
	if (wavInfo.chans < 3 || wavInfo.chans > 16) { fprintf(stderr, "ERROR: WAV file format not supported (%d channels, expected at least 3 and no more than 16).\n", wavInfo.chans); fclose(fp); return EXIT_DATAERR; }
	if (wavInfo.freq < 1 || wavInfo.freq > 48000) { fprintf(stderr, "ERROR: WAV file format not supported (%d frequency).\n", wavInfo.freq); fclose(fp); return EXIT_DATAERR; }

	// Extract metadata
	char *line;
	#define MAX_FIELDS 32
	//char *artistLines[MAX_FIELDS]; int numArtistLines = 0;
	//for (line = strtok(wavInfo.infoArtist, "\n"); line != NULL; line = strtok(NULL, "\n")) { if (numArtistLines < MAX_FIELDS) { artistLines[numArtistLines++] = line; } }
	//char *nameLines[MAX_FIELDS]; int numNameLines = 0;
	//for (line = strtok(wavInfo.infoName, "\n"); line != NULL; line = strtok(NULL, "\n")) { if (numNameLines < MAX_FIELDS) { nameLines[numNameLines++] = line; } }
	char *commentLines[MAX_FIELDS]; int numCommentLines = 0;
	for (line = strtok(wavInfo.infoComment, "\n"); line != NULL; line = strtok(NULL, "\n")) { if (numCommentLines < MAX_FIELDS) { commentLines[numCommentLines++] = line; } }

	// Parse headers
	bool parsedTime = false;
	bool parsedScale[10] = { 0 };
	double startTime = 0;
	for (i = 0; i < numCommentLines; i++)
	{
		if (strncmp(commentLines[i], "Time:", 5) == 0) 
		{
			startTime = ParseTime(commentLines[i] + 5);
			fprintf(stderr, "Time: %s\n", TimeString(startTime));
			if (startTime > 0) { parsedTime = true; }
		}
		else if (strncmp(commentLines[i], "Scale-", 6) == 0 && (commentLines[i][6] >= '1' && commentLines[i][6] <= '9') && commentLines[i][7] == ':')
		{
			int chan = commentLines[i][6] - '1';
			double val = atof(commentLines[i] + 8);
			scale[chan] = val / 32768.0;
			fprintf(stderr, "Scale-%d: %f (scale[%d] = %f)\n", chan + 1, val, chan, scale[chan]);
			if (scale[chan] > 0) { parsedScale[chan] = true; }
		}
	}

	// Check we parsed the headers we need
	if (!parsedTime) { fprintf(stderr, "WARNING: Didn't successfully parse a 'Time' header (using zero).\n"); }
	for (i = 0; i < 3; i++)
	{
		if (!parsedScale[i]) { fprintf(stderr, "WARNING: Didn't successfully parse a 'Scale-%d' header (using defaults).\n", i + 1); }
	}

	int bufferSamples = wavInfo.freq * 60 * 60;	// 1 hour buffer
	short *buffer = malloc(sizeof(short) * wavInfo.chans * bufferSamples);
	if (buffer == NULL) { fprintf(stderr, "ERROR: Problem allocating buffer for WAV file (%d samples).\n", bufferSamples); fclose(fp); return EXIT_SOFTWARE; }

	// Init. CSV/SVM/WTV/PAEE
	int outputOk = CalcInit(calc, wavInfo.freq, startTime);
	if (!outputOk)
	{
		fprintf(stderr, "ERROR: No outputs.\n");
		retVal = EXIT_CONFIG;
	}
	else
	{
		fprintf(stderr, "Working...\n");
		unsigned long samplesOffset = 0;
		unsigned long samplesRemaining = wavInfo.numSamples;
		while (!feof(fp))
		{
			long offset = wavInfo.offset + ((sizeof(short) * wavInfo.chans) * samplesOffset);
			unsigned long samplesToRead = bufferSamples;
			if (samplesToRead > samplesRemaining) { samplesToRead = samplesRemaining; }
			if (samplesToRead <= 0) { break; }
			fseek(fp, offset, SEEK_SET);
			unsigned long samplesRead = fread(buffer, sizeof(short) * wavInfo.chans, samplesToRead, fp);
			if (samplesRead <= 0) { break; }
			samplesOffset += samplesRead;
			samplesRemaining -= samplesRead;

			double values[3];
			for (i = 0; i < (int)samplesRead; i++)
			{
				const short *v = buffer + i * wavInfo.chans;

				// Auxilliary channel is last channel
				bool valid = true;
				if (wavInfo.chans > 3)
				{
					uint16_t aux = v[wavInfo.chans - 1];
					if (aux & WAV_AUX_UNAVAILABLE) { valid = false; }
				}

				// Scaling from metadata
				values[0] = v[0] * scale[0];
				values[1] = v[1] * scale[1];
				values[2] = v[2] * scale[2];
				if (!CalcAddValue(calc, values, 0.0, valid))
				{
					fprintf(stderr, "ERROR: Problem writing calculations.\n");
					retVal = EXIT_IOERR;
					break;
				}
			}
		}
	}

	free(buffer);
	fclose(fp);

	CalcClose(calc);

	return retVal;
}