Jump to content

Recommended Posts

Geschrieben

Required:

* two Sound Intensity bricklets, dangling some 50cm above where your heads are normally positioned in bed.

* [optional] Wifi module to pipe the collected data to your PC in another room

* some trivial software (below) continuously sampling the stereo bricklets, and dumping the measured values to files.

 

I chose to dump the samples as 32-bit floats so that I can import the "nightly dumps" into Audacity using its "File > Import > Raw Data" feature.

 

My setup produces 2 raw files, one for the "left" and "right" bed positions. Audacity quickly proves that my girlfriend was right in claiming I snore quite loudly.  :-[

 

package com.softwarepearls.apps.hardware.tinkerforge.health.snoring;

import static com.softwarepearls.lego.time.TimeAndDateKit.*;

import com.softwarepearls.lego.audio.enums.StereoPosition;
import com.softwarepearls.lego.filesystem.files.FileKit;
import com.softwarepearls.lego.hardware.tinkerforge.enums.BrickletType;
import com.softwarepearls.lego.hardware.tinkerforge.interfaces.input.SoundIntensity;
import com.softwarepearls.lego.hardware.tinkerforge.stack.BrickletDescriptor;
import com.softwarepearls.lego.hardware.tinkerforge.stack.TinkerForgeStack;
import com.softwarepearls.lego.java.system.SystemProperties;
import com.softwarepearls.lego.time.Frequency;
import com.softwarepearls.lego.time.TimeAndDateKit;
import com.tinkerforge.TinkerforgeException;

import java.io.*;
import java.util.Arrays;
import java.util.List;

/**
* Bare-bones two-person "sleep noise" recorder (meant to record snoring). For
* every night, produces two mono sound files holding the noise volume (not true
* sound!) recorded between 20:00 and 09:00.
* <P>
* Find out who snores the loudest, and when (apnea diagnoser?).
*/
public final class SleepRecorder implements Runnable {

private static final int RECORD_START_HOUR = 20;
private static final int RECORD_STOP_HOUR = 9;

private final static Frequency SAMPLING_FREQUENCY = Frequency.EVERY_10_MS;

// the following constants are specific to my personal setup. Modify to suit
// yours.
private final static String STACK_IP_ADDRESS = "192.168.0.114";
private final static String DUMP_FOLDER = "Documents/Audacity/SleepRecordings";

private final static String RIGHT_SENSOR_UID = "mkt";
private final static String LEFT_SENSOR_UID = "mmV";

private static final List<BrickletDescriptor> EXPECTED_BRICKLETS = Arrays.asList(

//
		new BrickletDescriptor(BrickletType.BRICKLET_SOUND_INTENSITY, "mkt"),//
		new BrickletDescriptor(BrickletType.BRICKLET_SOUND_INTENSITY, "mmV")//
		);

private DataOutputStream rightOut;
private DataOutputStream leftOut;

private void go() throws TinkerforgeException, IOException {

	Runtime.getRuntime().addShutdownHook(new Thread(this));

	final TinkerForgeStack tinkerForgeStack = TinkerForgeStack.initializeTinkerForgeStack(EXPECTED_BRICKLETS, STACK_IP_ADDRESS);
	final SoundIntensity rightSoundIntensity = (SoundIntensity) tinkerForgeStack.getBricklet(RIGHT_SENSOR_UID);
	final SoundIntensity leftSoundIntensity = (SoundIntensity) tinkerForgeStack.getBricklet(LEFT_SENSOR_UID);

	boolean recording = false;
	while (true) {
		if (recording) {
			recordSounds(rightSoundIntensity, leftSoundIntensity);

			recording = !waitForEnd();

			if (!recording) {
				closeFiles();
			}
			SAMPLING_FREQUENCY.delay();

		} else {

			recording = waitForStart();
			if (recording) {
				initFiles();
				continue;
			}
			Frequency.EVERY_10_SECOND.delay();
		}
	}
}

private void recordSounds(final SoundIntensity rightSoundIntensity, final SoundIntensity leftSoundIntensity) throws TinkerforgeException, IOException {

	final int rightIntensity = rightSoundIntensity.getIntensity();
	final int leftIntensity = leftSoundIntensity.getIntensity();
	writeToAudioFile(rightIntensity, StereoPosition.RIGHT);
	writeToAudioFile(leftIntensity, StereoPosition.LEFT);
}

private void initFiles() throws IOException {

	System.out.println("Initializing recordings for today " + currentDayOfMonth() + " " + currentMonth());

	rightOut = initRecordingFile(StereoPosition.RIGHT);
	leftOut = initRecordingFile(StereoPosition.LEFT);
}

private void closeFiles() throws IOException {

	System.out.println("Closing recordings.");

	rightOut.close();
	leftOut.close();
	rightOut = leftOut = null;
}

private DataOutputStream initRecordingFile(final StereoPosition stereoPosition) throws IOException {

	final File userHome = new File(SystemProperties.getUserHome());
	final File dumpRootDirectory = new File(userHome, DUMP_FOLDER);
	final File yearDirectory = new File(dumpRootDirectory, "" + currentYear());
	final String monthDirName = String.format("%02d_%s", currentMonthNumber() + 1, currentMonth());
	final File monthDirectory = new File(yearDirectory, monthDirName);
	FileKit.ensurePathExists(monthDirectory.getAbsolutePath());

	final String filename = String.format("%02d_%s_%s.raw", currentDayOfMonth(), currentDayName().substring(0, 3), stereoPosition);
	final File noiseFile = new File(monthDirectory, filename);
	System.out.println("Opened OK: " + noiseFile);
	final FileOutputStream fos = new FileOutputStream(noiseFile);
	final BufferedOutputStream bos = new BufferedOutputStream(fos);
	final DataOutputStream dos = new DataOutputStream(bos);

	return dos;
}

private void writeToAudioFile(final int intensity, final StereoPosition position) throws IOException {

	DataOutputStream out = rightOut;
	if (position == StereoPosition.LEFT) {
		out = leftOut;
	}
	final float floatIntensity = ((float) intensity) / 4096;
	out.writeFloat(floatIntensity);
}

private boolean waitForStart() {

	// return true;
	return TimeAndDateKit.currentHour() == RECORD_START_HOUR;
}

private boolean waitForEnd() {

	return TimeAndDateKit.currentHour() == RECORD_STOP_HOUR;
}

public static void main(final String[] args) throws TinkerforgeException, IOException {

	new SleepRecorder().go();
}

@Override
public void run() {

	try {
		closeFiles();
	}
	catch (final IOException e) {
		e.printStackTrace();
	}
}
}

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...