Skip to content
Snippets Groups Projects
Commit 1a2f06da authored by Paul Kaplan's avatar Paul Kaplan
Browse files

Add playhead

parent e0c95ccc
Branches
Tags
No related merge requests found
@import "../../css/colors.css";
.trim-container {
position: absolute;
......@@ -52,6 +53,10 @@
top: 0;
}
.playhead {
border: 1px solid $motion-primary;
}
.start-trim-line {
right: 0;
}
......
......@@ -25,6 +25,15 @@ const AudioTrimmer = props => (
</Box>
</Box>
{props.playhead ? (
<Box
className={classNames(styles.trimLine, styles.playhead)}
style={{
left: `${props.playhead}%`
}}
/>
) : null}
<Box
className={classNames(styles.trimBackground, styles.endTrimBackground)}
style={{
......@@ -49,6 +58,7 @@ const AudioTrimmer = props => (
AudioTrimmer.propTypes = {
onTrimEndMouseDown: PropTypes.func.isRequired,
onTrimStartMouseDown: PropTypes.func.isRequired,
playhead: PropTypes.number,
trimEnd: PropTypes.number.isRequired,
trimStart: PropTypes.number.isRequired
};
......
......@@ -30,6 +30,7 @@ const PlaybackStep = props => (
width={480}
/>
<AudioTrimmer
playhead={props.playhead}
trimEnd={props.trimEnd}
trimStart={props.trimStart}
onSetTrimEnd={props.onSetTrimEnd}
......@@ -77,6 +78,7 @@ PlaybackStep.propTypes = {
onSetTrimStart: PropTypes.func.isRequired,
onStopPlaying: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
playhead: PropTypes.number,
playing: PropTypes.bool.isRequired,
trimEnd: PropTypes.number.isRequired,
trimStart: PropTypes.number.isRequired
......
......@@ -18,12 +18,14 @@ const RecordModal = props => (
<PlaybackStep
encoding={props.encoding}
levels={props.levels}
playhead={props.playhead}
playing={props.playing}
samples={props.samples}
trimEnd={props.trimEnd}
trimStart={props.trimStart}
onBack={props.onBack}
onPlay={props.onPlay}
onSetPlayhead={props.onSetPlayhead}
onSetTrimEnd={props.onSetTrimEnd}
onSetTrimStart={props.onSetTrimStart}
onStopPlaying={props.onStopPlaying}
......@@ -47,11 +49,13 @@ RecordModal.propTypes = {
onCancel: PropTypes.func.isRequired,
onPlay: PropTypes.func.isRequired,
onRecord: PropTypes.func.isRequired,
onSetPlayhead: PropTypes.func.isRequired,
onSetTrimEnd: PropTypes.func.isRequired,
onSetTrimStart: PropTypes.func.isRequired,
onStopPlaying: PropTypes.func.isRequired,
onStopRecording: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
playhead: PropTypes.number,
playing: PropTypes.bool,
recording: PropTypes.bool,
samples: PropTypes.instanceOf(Float32Array),
......
......@@ -48,6 +48,7 @@ class AudioTrimmer extends React.Component {
render () {
return (
<AudioTrimmerComponent
playhead={this.props.playhead}
trimEnd={this.props.trimEnd}
trimStart={this.props.trimStart}
onTrimEndMouseDown={this.handleTrimEndMouseDown}
......@@ -60,6 +61,7 @@ class AudioTrimmer extends React.Component {
AudioTrimmer.propTypes = {
onSetTrimEnd: PropTypes.func,
onSetTrimStart: PropTypes.func,
playhead: PropTypes.number,
trimEnd: PropTypes.number,
trimStart: PropTypes.number
};
......
......@@ -19,7 +19,12 @@ class PlaybackStep extends React.Component {
this.audioBufferPlayer.stop();
}
handlePlay () {
this.audioBufferPlayer.play(this.props.trimStart, this.props.trimEnd, this.props.onStopPlaying);
this.audioBufferPlayer.play(
this.props.trimStart,
this.props.trimEnd,
this.props.onSetPlayhead,
this.props.onStopPlaying
);
this.props.onPlay();
}
handleStopPlaying () {
......@@ -30,6 +35,7 @@ class PlaybackStep extends React.Component {
const {
onPlay, // eslint-disable-line no-unused-vars
onStopPlaying, // eslint-disable-line no-unused-vars
onSetPlayhead, // eslint-disable-line no-unused-vars
...componentProps
} = this.props;
return (
......
......@@ -22,6 +22,7 @@ class RecordModal extends React.Component {
'handleBack',
'handleSubmit',
'handleCancel',
'handleSetPlayhead',
'handleSetTrimStart',
'handleSetTrimEnd'
]);
......@@ -30,6 +31,7 @@ class RecordModal extends React.Component {
samples: null,
encoding: false,
levels: null,
playhead: null,
playing: false,
recording: false,
sampleRate: null,
......@@ -47,7 +49,7 @@ class RecordModal extends React.Component {
this.setState({playing: true});
}
handleStopPlaying () {
this.setState({playing: false});
this.setState({playing: false, playhead: null});
}
handleBack () {
this.setState({playing: false, samples: null});
......@@ -58,6 +60,9 @@ class RecordModal extends React.Component {
handleSetTrimStart (trimStart) {
this.setState({trimStart});
}
handleSetPlayhead (playhead) {
this.setState({playhead});
}
handleSubmit () {
this.setState({encoding: true}, () => {
const sampleCount = this.state.samples.length;
......@@ -97,6 +102,7 @@ class RecordModal extends React.Component {
<RecordModalComponent
encoding={this.state.encoding}
levels={this.state.levels}
playhead={this.state.playhead}
playing={this.state.playing}
recording={this.state.recording}
samples={this.state.samples}
......@@ -106,6 +112,7 @@ class RecordModal extends React.Component {
onCancel={this.handleCancel}
onPlay={this.handlePlay}
onRecord={this.handleRecord}
onSetPlayhead={this.handleSetPlayhead}
onSetTrimEnd={this.handleSetTrimEnd}
onSetTrimStart={this.handleSetTrimStart}
onStopPlaying={this.handleStopPlaying}
......
......@@ -6,9 +6,16 @@ class AudioBufferPlayer {
this.buffer = this.audioContext.createBuffer(1, samples.length, this.audioContext.sampleRate);
this.buffer.getChannelData(0).set(samples);
this.source = null;
this.stopped = true;
}
play (trimStart, trimEnd, onEnded) {
play (trimStart, trimEnd, onUpdate, onEnded) {
this.stopped = false;
this.updateCallback = onUpdate;
this.trimStart = trimStart;
this.trimEnd = trimEnd;
this.startTime = Date.now();
const trimStartTime = this.buffer.duration * trimStart / 100;
const trimmedDuration = this.buffer.duration * trimEnd / 100 - trimStartTime;
......@@ -17,6 +24,17 @@ class AudioBufferPlayer {
this.source.buffer = this.buffer;
this.source.connect(this.audioContext.destination);
this.source.start(0, trimStartTime, trimmedDuration);
this.update();
}
update () {
const timeSinceStart = (Date.now() - this.startTime) / 1000;
const percentage = 100 * timeSinceStart / this.buffer.duration;
if (percentage + this.trimStart < this.trimEnd && this.source.onended) {
requestAnimationFrame(this.update.bind(this));
this.updateCallback(percentage + this.trimStart);
}
}
stop () {
......
......@@ -102,7 +102,7 @@ class AudioRecorder {
}
}
const trimStart = 100 * Math.max(1, firstChunkAboveThreshold - 2) / this.buffers.length;
const trimStart = 100 * Math.max(2, firstChunkAboveThreshold - 2) / this.buffers.length;
const trimEnd = 100 * Math.min(this.buffers.length - 2, lastChunkAboveThreshold + 2) / this.buffers.length;
const buffer = new Float32Array(this.buffers.length * this.bufferLength);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment