@@ -11,6 +11,7 @@ import {
11
11
OctraAnnotation ,
12
12
OctraAnnotationAnyLevel ,
13
13
OctraAnnotationSegment ,
14
+ OctraAnnotationSegmentLevel ,
14
15
OLabel ,
15
16
} from '@octra/annotation' ;
16
17
import { Subject } from 'rxjs' ;
@@ -27,7 +28,10 @@ import {
27
28
providedIn : 'root' ,
28
29
} )
29
30
export class AudioViewerService {
30
- get boundaryDragging ( ) : Subject < 'started' | 'stopped' > {
31
+ get boundaryDragging ( ) : Subject < {
32
+ status : 'started' | 'stopped' | 'dragging' ;
33
+ shiftPressed ?: boolean ;
34
+ } > {
31
35
return this . _boundaryDragging ;
32
36
}
33
37
@@ -60,7 +64,10 @@ export class AudioViewerService {
60
64
protected mouseClickPos : SampleUnit | undefined ;
61
65
protected playcursor : PlayCursor | undefined ;
62
66
63
- private _boundaryDragging : Subject < 'started' | 'stopped' > ;
67
+ private _boundaryDragging : Subject < {
68
+ status : 'started' | 'stopped' | 'dragging' ;
69
+ shiftPressed ?: boolean ;
70
+ } > ;
64
71
currentLevelID ?: number ;
65
72
66
73
annotation ?: OctraAnnotation < ASRContext , OctraAnnotationSegment > ;
@@ -134,7 +141,10 @@ export class AudioViewerService {
134
141
set dragableBoundaryNumber ( value : number ) {
135
142
if ( value > - 1 && this . _dragableBoundaryNumber === - 1 ) {
136
143
// started
137
- this . _boundaryDragging . next ( 'started' ) ;
144
+ this . _boundaryDragging . next ( {
145
+ shiftPressed : this . shiftPressed ,
146
+ status : 'started' ,
147
+ } ) ;
138
148
}
139
149
this . _dragableBoundaryNumber = value ;
140
150
}
@@ -185,7 +195,10 @@ export class AudioViewerService {
185
195
}
186
196
187
197
constructor ( private multiThreadingService : MultiThreadingService ) {
188
- this . _boundaryDragging = new Subject < 'started' | 'stopped' > ( ) ;
198
+ this . _boundaryDragging = new Subject < {
199
+ status : 'started' | 'stopped' | 'dragging' ;
200
+ shiftPressed ?: boolean ;
201
+ } > ( ) ;
189
202
}
190
203
191
204
public initialize ( innerWidth : number , audioChunk : AudioChunk ) {
@@ -233,7 +246,9 @@ export class AudioViewerService {
233
246
this . audioChunk . startpos = this . mouseClickPos . clone ( ) ;
234
247
this . audioChunk . selection . start = absXInTime . clone ( ) ;
235
248
this . audioChunk . selection . end = absXInTime . clone ( ) ;
236
- this . _drawnSelection = this . audioChunk . selection . clone ( ) ;
249
+ if ( ! this . shiftPressed ) {
250
+ this . _drawnSelection = this . audioChunk . selection . clone ( ) ;
251
+ }
237
252
238
253
if ( this . _dragableBoundaryNumber > - 1 ) {
239
254
const segmentBefore = (
@@ -286,23 +301,108 @@ export class AudioViewerService {
286
301
) ?. clone ( ) ;
287
302
288
303
if ( segment ) {
289
- segment . time = this . audioTCalculator . absXChunktoSampleUnit (
290
- absX ,
291
- this . audioChunk
292
- ) ! ;
293
-
294
- this . currentLevelChange . emit ( {
295
- type : 'change' ,
296
- items : [
297
- {
298
- instance : segment ,
299
- } ,
300
- ] ,
301
- } ) ;
302
- this . annotationChange . emit ( this . annotation ) ;
304
+ if ( ! this . shiftPressed ) {
305
+ // move only this boundary
306
+ segment . time = this . audioTCalculator . absXChunktoSampleUnit (
307
+ absX ,
308
+ this . audioChunk
309
+ ) ! ;
310
+
311
+ this . currentLevelChange . emit ( {
312
+ type : 'change' ,
313
+ items : [
314
+ {
315
+ instance : segment ,
316
+ } ,
317
+ ] ,
318
+ } ) ;
319
+ this . annotationChange . emit ( this . annotation ) ;
320
+ } else if ( this . drawnSelection ?. duration ?. samples ) {
321
+ // move all segments with difference to left or right
322
+ const oldSamplePosition = segment . time . samples ;
323
+ const newSamplePosition =
324
+ this . audioTCalculator . absXChunktoSampleUnit (
325
+ absX ,
326
+ this . audioChunk
327
+ ) ?. samples ;
328
+ const diff = newSamplePosition ! - oldSamplePosition ;
329
+ let changedItems : OctraAnnotationSegment [ ] = [ ] ;
330
+
331
+ if ( diff > 0 ) {
332
+ // shift to right
333
+ for ( const currentLevelElement of ( this . annotation
334
+ . currentLevel as OctraAnnotationSegmentLevel < OctraAnnotationSegment > ) !
335
+ . items ) {
336
+ if (
337
+ currentLevelElement . time . samples >=
338
+ segment . time . samples &&
339
+ currentLevelElement . time . samples + diff <
340
+ this . drawnSelection . end ! . samples
341
+ ) {
342
+ const newItem = currentLevelElement . clone (
343
+ currentLevelElement . id
344
+ ) ;
345
+ newItem . time = currentLevelElement . time . add (
346
+ this . audioManager . createSampleUnit ( diff )
347
+ ) ;
348
+ this . annotation =
349
+ this . annotation . changeCurrentItemById (
350
+ currentLevelElement . id ,
351
+ newItem
352
+ ) ;
353
+ changedItems . push ( newItem ) ;
354
+ }
355
+ }
356
+ } else {
357
+ // shift to left
358
+ for ( const currentLevelElement of ( this . annotation
359
+ . currentLevel as OctraAnnotationSegmentLevel < OctraAnnotationSegment > ) !
360
+ . items ) {
361
+ console . log (
362
+ `move to ${ currentLevelElement . time . samples + diff } `
363
+ ) ;
364
+ if (
365
+ currentLevelElement . time . samples <=
366
+ segment . time . samples &&
367
+ currentLevelElement . time . samples + diff >
368
+ this . drawnSelection . start ! . samples
369
+ ) {
370
+ const newItem = currentLevelElement . clone (
371
+ currentLevelElement . id
372
+ ) ;
373
+ newItem . time = currentLevelElement . time . add (
374
+ this . audioManager . createSampleUnit ( diff )
375
+ ) ;
376
+ this . annotation =
377
+ this . annotation . changeCurrentItemById (
378
+ currentLevelElement . id ,
379
+ newItem
380
+ ) ;
381
+ changedItems . push ( newItem ) ;
382
+ } else if (
383
+ currentLevelElement . time . samples - diff <
384
+ 0
385
+ ) {
386
+ changedItems = [ ] ;
387
+ break ;
388
+ }
389
+ }
390
+ }
391
+
392
+ if ( changedItems . length > 0 ) {
393
+ this . currentLevelChange . emit ( {
394
+ type : 'change' ,
395
+ items : changedItems . map ( ( a ) => ( { instance : a } ) ) ,
396
+ } ) ;
397
+ this . annotationChange . emit ( this . annotation ) ;
398
+ }
399
+ }
303
400
}
304
401
305
- this . _boundaryDragging . next ( 'stopped' ) ;
402
+ this . _boundaryDragging . next ( {
403
+ shiftPressed : this . shiftPressed ,
404
+ status : 'stopped' ,
405
+ } ) ;
306
406
} else {
307
407
// set selection
308
408
this . audioChunk . selection . end = absXInTime . clone ( ) ;
@@ -612,8 +712,11 @@ export class AudioViewerService {
612
712
613
713
if ( this . mouseDown && this . _dragableBoundaryNumber < 0 ) {
614
714
// mouse down, nothing dragged
615
- this . audioChunk . selection . end = absXTime . clone ( ) ;
616
- this . _drawnSelection = this . audioChunk . selection . clone ( ) ;
715
+ if ( ! this . shiftPressed ) {
716
+ console . log ( 'reset selection' ) ;
717
+ this . audioChunk . selection . end = absXTime . clone ( ) ;
718
+ this . _drawnSelection = this . audioChunk . selection . clone ( ) ;
719
+ }
617
720
} else if (
618
721
this . settings . boundaries . enabled &&
619
722
this . mouseDown &&
0 commit comments