Commit bd6f38f2 authored by Omniscimus's avatar Omniscimus Committed by Michael Henretty
Browse files

Recording sense checks (#432)

* Add recording length check

* Add recording volume check

* Sense check recordings before checking if set is complete

* Use const where possible in recording sense checks

* Return enum value instead of strings for recording validity

* Change min recording length to 300 ms

* Refactor some functions in record.tsx

* For invalid recordings, just log a message to the console for now
parent 21100886
...@@ -15,6 +15,15 @@ import confirm from '../confirm'; ...@@ -15,6 +15,15 @@ import confirm from '../confirm';
const CACHE_SET_COUNT = 9; const CACHE_SET_COUNT = 9;
const SET_COUNT = 3; const SET_COUNT = 3;
const PAGE_NAME = 'record'; const PAGE_NAME = 'record';
const MIN_RECORDING_LENGTH = 300; // ms
const MAX_RECORDING_LENGTH = 10000; // ms
const MIN_VOLUME = 1;
enum RecordingError {
TOO_SHORT = 1,
TOO_LONG,
TOO_QUIET
};
interface RecordProps { interface RecordProps {
active: string; active: string;
...@@ -34,6 +43,7 @@ interface RecordState { ...@@ -34,6 +43,7 @@ interface RecordState {
sentences: string[]; sentences: string[];
recording: boolean; recording: boolean;
recordingStartTime: number; recordingStartTime: number;
recordingStopTime: number;
recordings: any[]; recordings: any[];
uploading: boolean; uploading: boolean;
uploadProgress: number; uploadProgress: number;
...@@ -46,11 +56,13 @@ export default class RecordPage extends Component<RecordProps, RecordState> { ...@@ -46,11 +56,13 @@ export default class RecordPage extends Component<RecordProps, RecordState> {
isUnsupportedPlatform: boolean; isUnsupportedPlatform: boolean;
tracker: Tracker; tracker: Tracker;
sentenceCache: string[]; sentenceCache: string[];
maxVolume: number;
state = { state = {
sentences: [], sentences: [],
recording: false, recording: false,
recordingStartTime: 0, recordingStartTime: 0,
recordingStopTime: 0,
recordings: [], recordings: [],
uploading: false, uploading: false,
uploadProgress: 0, uploadProgress: 0,
...@@ -88,6 +100,8 @@ export default class RecordPage extends Component<RecordProps, RecordState> { ...@@ -88,6 +100,8 @@ export default class RecordPage extends Component<RecordProps, RecordState> {
return; return;
} }
this.maxVolume = 0;
// Bind now, to avoid memory leak when setting handler. // Bind now, to avoid memory leak when setting handler.
this.onSubmit = this.onSubmit.bind(this); this.onSubmit = this.onSubmit.bind(this);
this.onRecordClick = this.onRecordClick.bind(this); this.onRecordClick = this.onRecordClick.bind(this);
...@@ -115,6 +129,26 @@ export default class RecordPage extends Component<RecordProps, RecordState> { ...@@ -115,6 +129,26 @@ export default class RecordPage extends Component<RecordProps, RecordState> {
this.props.onRecordStop && this.props.onRecordStop(); this.props.onRecordStop && this.props.onRecordStop();
const error = this.getRecordingError();
if (error) {
let message;
switch (error) {
case RecordingError.TOO_SHORT:
message = 'The recording was too short.';
break;
case RecordingError.TOO_LONG:
message = 'The recording was too long.';
break;
case RecordingError.TOO_QUIET:
message = 'The recording was too quiet.';
break;
default:
message = 'There was something wrong with the recording.';
}
console.log(message);
// TODO display error to user
}
if (!this.props.onRecordingSet) { if (!this.props.onRecordingSet) {
return; return;
} }
...@@ -124,6 +158,20 @@ export default class RecordPage extends Component<RecordProps, RecordState> { ...@@ -124,6 +158,20 @@ export default class RecordPage extends Component<RecordProps, RecordState> {
} }
} }
private getRecordingError(): RecordingError {
const length = this.state.recordingStopTime - this.state.recordingStartTime;
if (length < MIN_RECORDING_LENGTH) {
return RecordingError.TOO_SHORT;
}
if (length > MAX_RECORDING_LENGTH) {
return RecordingError.TOO_LONG;
}
if (this.maxVolume < MIN_VOLUME) {
return RecordingError.TOO_QUIET;
}
return null;
}
private deleteRecording(index: number): void { private deleteRecording(index: number): void {
// Move redo sentence to the end. // Move redo sentence to the end.
let sentences = this.state.sentences; let sentences = this.state.sentences;
...@@ -156,11 +204,19 @@ export default class RecordPage extends Component<RecordProps, RecordState> { ...@@ -156,11 +204,19 @@ export default class RecordPage extends Component<RecordProps, RecordState> {
} }
private updateVolume(volume: number) { private updateVolume(volume: number) {
if (!this.state.recording || !this.props.onVolume) { if (!this.state.recording) {
return; return;
} }
this.props.onVolume(volume); // For some reason, volume is always exactly 100 at the end of the
// recording, even if it is silent; so ignore that.
if (volume !== 100 && volume > this.maxVolume) {
this.maxVolume = volume;
}
if (this.props.onVolume) {
this.props.onVolume(volume);
}
} }
private async onSubmit() { private async onSubmit() {
...@@ -239,16 +295,21 @@ export default class RecordPage extends Component<RecordProps, RecordState> { ...@@ -239,16 +295,21 @@ export default class RecordPage extends Component<RecordProps, RecordState> {
startRecording() { startRecording() {
this.audio.start(); this.audio.start();
this.maxVolume = 0;
this.setState({ this.setState({
recording: true, recording: true,
// TODO: reanble display of recording time at some point. // TODO: reanble display of recording time at some point.
// recordingStartTime: this.audio.audioContext.currentTime recordingStartTime: Date.now(),
recordingStopTime: 0,
}); });
this.props.onRecord && this.props.onRecord(); this.props.onRecord && this.props.onRecord();
} }
stopRecording() { stopRecording() {
this.audio.stop().then(this.processRecording);; this.audio.stop().then(this.processRecording);
this.setState({
recordingStopTime: Date.now()
});
} }
/** /**
...@@ -306,7 +367,7 @@ export default class RecordPage extends Component<RecordProps, RecordState> { ...@@ -306,7 +367,7 @@ export default class RecordPage extends Component<RecordProps, RecordState> {
// Get the text prompts. // Get the text prompts.
for (let i = 0; i < SET_COUNT; i++) { for (let i = 0; i < SET_COUNT; i++) {
// For the sentences elements, we need to // For the sentences elements, we need to
// figure out where each item is positioned. // figure out where each item is positioned.
let className = 'text-box'; let className = 'text-box';
let length = this.state.recordings.length; let length = this.state.recordings.length;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment