aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/AudioWaveform.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/AudioWaveform.tsx')
-rw-r--r--src/client/views/AudioWaveform.tsx165
1 files changed, 122 insertions, 43 deletions
diff --git a/src/client/views/AudioWaveform.tsx b/src/client/views/AudioWaveform.tsx
index 7ff9c1071..313d0062e 100644
--- a/src/client/views/AudioWaveform.tsx
+++ b/src/client/views/AudioWaveform.tsx
@@ -6,56 +6,135 @@ import Waveform from "react-audio-waveform";
import { Doc } from "../../fields/Doc";
import { List } from "../../fields/List";
import { listSpec } from "../../fields/Schema";
-import { Cast } from "../../fields/Types";
+import { Cast, NumCast } from "../../fields/Types";
import { numberRange } from "../../Utils";
import "./AudioWaveform.scss";
export interface AudioWaveformProps {
- duration: number;
- mediaPath: string;
- dataDoc: Doc;
- PanelHeight: () => number;
+ duration: number;
+ mediaPath: string;
+ dataDoc: Doc;
+ trimming: boolean;
+ PanelHeight: () => number;
}
@observer
export class AudioWaveform extends React.Component<AudioWaveformProps> {
- public static NUMBER_OF_BUCKETS = 100;
- @computed get _waveHeight() { return Math.max(50, this.props.PanelHeight()); }
- componentDidMount() {
- const audioBuckets = Cast(this.props.dataDoc.audioBuckets, listSpec("number"), []);
- if (!audioBuckets.length) {
- this.props.dataDoc.audioBuckets = new List<number>([0, 0]); /// "lock" to prevent other views from computing the same data
- setTimeout(this.createWaveformBuckets);
- }
- }
- // decodes the audio file into peaks for generating the waveform
- createWaveformBuckets = async () => {
- axios({ url: this.props.mediaPath, responseType: "arraybuffer" })
- .then(response => {
- const context = new window.AudioContext();
- context.decodeAudioData(response.data,
- action(buffer => {
- const decodedAudioData = buffer.getChannelData(0);
- const bucketDataSize = Math.floor(decodedAudioData.length / AudioWaveform.NUMBER_OF_BUCKETS);
- const brange = Array.from(Array(bucketDataSize));
- this.props.dataDoc.audioBuckets = new List<number>(
- numberRange(AudioWaveform.NUMBER_OF_BUCKETS).map((i: number) =>
- brange.reduce((p, x, j) => Math.abs(Math.max(p, decodedAudioData[i * bucketDataSize + j])), 0) / 2));
- }));
- });
+ public static NUMBER_OF_BUCKETS = 100;
+ @computed get _waveHeight() {
+ return Math.max(50, this.props.PanelHeight());
+ }
+ componentDidMount() {
+ const audioBuckets = Cast(
+ this.props.dataDoc.audioBuckets,
+ listSpec("number"),
+ []
+ );
+ if (!audioBuckets.length) {
+ this.props.dataDoc.audioBuckets = new List<number>([0, 0]); /// "lock" to prevent other views from computing the same data
+ setTimeout(this.createWaveformBuckets);
}
- render() {
- const audioBuckets = Cast(this.props.dataDoc.audioBuckets, listSpec("number"), []);
- return <div className="audioWaveform">
- <Waveform
- color={"darkblue"}
- height={this._waveHeight}
- barWidth={0.1}
- pos={this.props.duration}
- duration={this.props.duration}
- peaks={audioBuckets.length === AudioWaveform.NUMBER_OF_BUCKETS ? audioBuckets : undefined}
- progressColor={"blue"} />
- </div>;
- }
-} \ No newline at end of file
+ // const trimBuckets = Cast(
+ // this.props.dataDoc.trimBuckets,
+ // listSpec("number"),
+ // []
+ // );
+ // if (!trimBuckets.length) {
+ // this.props.dataDoc.trimBuckets = new List<number>([0, 0]); /// "lock" to prevent other views from computing the same data
+ // this.createTrimBuckets();
+ // }
+ }
+ // decodes the audio file into peaks for generating the waveform
+ createWaveformBuckets = async () => {
+ axios({ url: this.props.mediaPath, responseType: "arraybuffer" }).then(
+ (response) => {
+ const context = new window.AudioContext();
+ context.decodeAudioData(
+ response.data,
+ action((buffer) => {
+ const decodedAudioData = buffer.getChannelData(0);
+
+ const bucketDataSize = Math.floor(
+ decodedAudioData.length / AudioWaveform.NUMBER_OF_BUCKETS
+ );
+ const brange = Array.from(Array(bucketDataSize));
+ this.props.dataDoc.audioBuckets = new List<number>(
+ numberRange(AudioWaveform.NUMBER_OF_BUCKETS).map(
+ (i: number) =>
+ brange.reduce(
+ (p, x, j) =>
+ Math.abs(
+ Math.max(p, decodedAudioData[i * bucketDataSize + j])
+ ),
+ 0
+ ) / 2
+ )
+ );
+ })
+ );
+ }
+ );
+ };
+
+ @action
+ createTrimBuckets = () => {
+ const audioBuckets = Cast(
+ this.props.dataDoc.audioBuckets,
+ listSpec("number"),
+ []
+ );
+
+ const start = Math.floor(
+ (NumCast(this.props.dataDoc.clipStart) / this.props.duration) * 100
+ );
+ const end = Math.floor(
+ (NumCast(this.props.dataDoc.clipEnd) / this.props.duration) * 100
+ );
+ return audioBuckets.slice(start, end);
+ };
+
+ render() {
+ const audioBuckets = Cast(
+ this.props.dataDoc.audioBuckets,
+ listSpec("number"),
+ []
+ );
+
+ const trimBuckets = Cast(
+ this.props.dataDoc.trimBuckets,
+ listSpec("number"),
+ []
+ );
+
+ return (
+ <div className="audioWaveform">
+ {this.props.trimming ? (
+ <Waveform
+ color={"darkblue"}
+ height={this._waveHeight}
+ barWidth={0.1}
+ pos={this.props.duration}
+ duration={this.props.duration}
+ peaks={
+ audioBuckets.length === AudioWaveform.NUMBER_OF_BUCKETS
+ ? audioBuckets
+ : undefined
+ }
+ progressColor={"blue"}
+ />
+ ) : (
+ <Waveform
+ color={"darkblue"}
+ height={this._waveHeight}
+ barWidth={0.1}
+ pos={this.props.duration}
+ duration={this.props.duration}
+ peaks={this.createTrimBuckets()}
+ progressColor={"blue"}
+ />
+ )}
+ </div>
+ );
+ }
+}