mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Play selection / cursor
This commit is contained in:
parent
72c4ac4d2b
commit
19c8663dcd
|
@ -11,6 +11,7 @@
|
|||
#import "VLModel.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "VLKeyValueUndo.h"
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
|
||||
@class VLSheetWindow;
|
||||
|
||||
|
@ -56,7 +57,7 @@ enum {
|
|||
NSMutableDictionary*validTmpFiles;
|
||||
int repeatVolta;
|
||||
bool brandNew;
|
||||
bool hasMusicSequence;
|
||||
MusicSequence musicSequence;
|
||||
VLSheetWindow * sheetWin;
|
||||
VLKeyValueUndo* undo;
|
||||
VLKeyValueUndo* staffMetrics;
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
vcsWrapper = nil;
|
||||
repeatVolta = 2;
|
||||
brandNew = true;
|
||||
hasMusicSequence = false;
|
||||
musicSequence = nil;
|
||||
playRate = 1.0;
|
||||
validTmpFiles = [[NSMutableDictionary alloc] initWithCapacity:10];
|
||||
[self setHasUndoManager:YES];
|
||||
|
@ -138,7 +138,7 @@
|
|||
|
||||
- (void)updateChangeCount:(NSDocumentChangeType)changeType
|
||||
{
|
||||
hasMusicSequence = false;
|
||||
musicSequence = nil;
|
||||
[validTmpFiles removeAllObjects];
|
||||
[super updateChangeCount:changeType];
|
||||
}
|
||||
|
@ -458,15 +458,16 @@
|
|||
|
||||
- (void) playSong
|
||||
{
|
||||
if (hasMusicSequence) {
|
||||
if (musicSequence) {
|
||||
void (^finalizer)() = [sheetWin willPlaySequence:musicSequence];
|
||||
VLSoundOut::Instance()->PlaySequence(NULL);
|
||||
finalizer();
|
||||
} else {
|
||||
[self createTmpFileWithExtension:@"mid" ofType:VLMIDIType];
|
||||
|
||||
MusicSequence music;
|
||||
NewMusicSequence(&music);
|
||||
NewMusicSequence(&musicSequence);
|
||||
|
||||
MusicSequenceFileLoad(music, (CFURLRef)[self fileURLWithExtension:@"mid"],
|
||||
MusicSequenceFileLoad(musicSequence, (CFURLRef)[self fileURLWithExtension:@"mid"],
|
||||
0, 0);
|
||||
|
||||
size_t countIn = 0;
|
||||
|
@ -477,14 +478,14 @@
|
|||
case 0x608:
|
||||
countIn = 2;
|
||||
}
|
||||
VLMIDIWriter annotate(music, countIn);
|
||||
VLMIDIWriter annotate(musicSequence, countIn);
|
||||
annotate.Visit(*song);
|
||||
|
||||
hasMusicSequence = true;
|
||||
[sheetWin willPlaySequence:music];
|
||||
baseTempo = songTempo;
|
||||
VLSoundOut::Instance()->SetPlayRate(playRate);
|
||||
VLSoundOut::Instance()->PlaySequence(music);
|
||||
void (^finalizer)() = [sheetWin willPlaySequence:musicSequence];
|
||||
VLSoundOut::Instance()->SetPlayRate(playRate);
|
||||
VLSoundOut::Instance()->PlaySequence(musicSequence);
|
||||
finalizer();
|
||||
}
|
||||
[self setPlayElements:[self playElements]];
|
||||
}
|
||||
|
@ -494,7 +495,7 @@
|
|||
NSString * savedGroove = songGroove;
|
||||
[validTmpFiles removeObjectForKey:@"mma"];
|
||||
[validTmpFiles removeObjectForKey:@"mid"];
|
||||
hasMusicSequence = false;
|
||||
musicSequence = nil;
|
||||
songGroove = groove;
|
||||
previewRange = sections;
|
||||
playElements |= kVLPlayGroovePreview;
|
||||
|
@ -503,7 +504,7 @@
|
|||
songGroove = savedGroove;
|
||||
[validTmpFiles removeObjectForKey:@"mma"];
|
||||
[validTmpFiles removeObjectForKey:@"mid"];
|
||||
hasMusicSequence = false;
|
||||
musicSequence = nil;
|
||||
}
|
||||
|
||||
- (NSPrintOperation *)printOperationWithSettings:(NSDictionary *)printSettings
|
||||
|
|
|
@ -11,6 +11,50 @@
|
|||
#include "VLMIDIWriter.h"
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
|
||||
VLMIDIUtilities::VLMIDIUtilities(MusicSequence music)
|
||||
: fMusic(music)
|
||||
{
|
||||
}
|
||||
|
||||
MusicTimeStamp VLMIDIUtilities::Length()
|
||||
{
|
||||
UInt32 ntracks;
|
||||
MusicSequenceGetTrackCount(fMusic, &ntracks);
|
||||
MusicTimeStamp sequenceLength = 0;
|
||||
for (UInt32 i = 0; i < ntracks; ++i) {
|
||||
MusicTrack track;
|
||||
MusicTimeStamp trackLength;
|
||||
UInt32 propsize = sizeof(MusicTimeStamp);
|
||||
MusicSequenceGetIndTrack(fMusic, i, &track);
|
||||
MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
|
||||
&trackLength, &propsize);
|
||||
sequenceLength = std::max(sequenceLength, trackLength);
|
||||
}
|
||||
return sequenceLength;
|
||||
}
|
||||
|
||||
MusicTimeStamp VLMIDIUtilities::Find(VLLocation at)
|
||||
{
|
||||
UInt32 ntracks;
|
||||
MusicSequenceGetTrackCount(fMusic, &ntracks);
|
||||
MusicTrack track;
|
||||
MusicSequenceGetIndTrack(fMusic, ntracks-1, &track);
|
||||
MusicEventIterator iter;
|
||||
NewMusicEventIterator(track, &iter);
|
||||
Boolean hasEvent;
|
||||
while (!MusicEventIteratorHasCurrentEvent(iter, &hasEvent) && hasEvent) {
|
||||
MusicTimeStamp ts;
|
||||
MusicEventType ty;
|
||||
const VLMIDIUserEvent * data;
|
||||
UInt32 sz;
|
||||
MusicEventIteratorGetEventInfo(iter, &ts, &ty, (const void **)&data, &sz);
|
||||
if (ty == kMusicEventType_User && data->fAt >= at)
|
||||
return ts;
|
||||
MusicEventIteratorNextEvent(iter);
|
||||
}
|
||||
return Length();
|
||||
}
|
||||
|
||||
struct VLMetaEvent : MIDIMetaEvent {
|
||||
char fPadding[32];
|
||||
|
||||
|
|
|
@ -20,6 +20,16 @@ struct VLMIDIUserEvent {
|
|||
VLLocation fAt;
|
||||
};
|
||||
|
||||
class VLMIDIUtilities {
|
||||
public:
|
||||
VLMIDIUtilities(MusicSequence music);
|
||||
|
||||
MusicTimeStamp Length();
|
||||
MusicTimeStamp Find(VLLocation at);
|
||||
public:
|
||||
MusicSequence fMusic;
|
||||
};
|
||||
|
||||
class VLMIDIWriter: public VLSongVisitor {
|
||||
public:
|
||||
VLMIDIWriter(MusicSequence music, size_t countIn)
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include <string>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef __VLMODEL__
|
||||
#define __VLMODEL__
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark class VLFraction
|
||||
|
||||
|
@ -497,6 +500,8 @@ protected:
|
|||
void VisitChords(VLMeasure & measure);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode:C++
|
||||
// End:
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
|
||||
- (void)updateMenus;
|
||||
|
||||
- (void) willPlaySequence:(MusicSequence)music;
|
||||
- (void (^)()) willPlaySequence:(MusicSequence)music;
|
||||
- (void) playWasPaused;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#import "VLSheetWindow.h"
|
||||
#import "VLDocument.h"
|
||||
#import "VLPitchGrid.h"
|
||||
#import "VLSoundOut.h"
|
||||
#import "VLMIDIWriter.h"
|
||||
|
||||
#pragma mark VLMeasureEditable
|
||||
|
||||
|
@ -126,6 +128,11 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[fView setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void) userEvent:(const VLMIDIUserEvent *) event
|
||||
{
|
||||
if (event->fPitch) {
|
||||
|
@ -583,12 +590,28 @@ inline int TimeTag(const VLProperties & prop)
|
|||
[self updateGrooveMenu];
|
||||
}
|
||||
|
||||
- (void) willPlaySequence:(MusicSequence)music
|
||||
- (void (^)()) willPlaySequence:(MusicSequence)music
|
||||
{
|
||||
uint32_t selStart = fSelStart;
|
||||
uint32_t selEnd = fSelEnd;
|
||||
|
||||
VLEditable * e =
|
||||
[[VLPlaybackEditable alloc] initWithView:self];
|
||||
[self setEditTarget:e];
|
||||
MusicSequenceSetUserCallback(music, VLSequenceCallback, e);
|
||||
|
||||
return [Block_copy(^{
|
||||
if (selEnd != kNoMeasure) {
|
||||
VLMIDIUtilities locator(music);
|
||||
VLLocation start = {selStart, VLFraction(0)};
|
||||
VLLocation end = {selEnd, VLFraction(0)};
|
||||
VLSoundOut::Instance()->SetStart(locator.Find(start));
|
||||
if (selEnd > selStart) {
|
||||
VLSoundOut::Instance()->SetEnd(locator.Find(end));
|
||||
[self selectMeasure:selStart to:selEnd];
|
||||
}
|
||||
}
|
||||
}) autorelease];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
- (void) setEditTarget:(VLEditable *)editable;
|
||||
- (void) startAnimation;
|
||||
- (void) stopAnimation;
|
||||
- (void) willPlaySequence:(MusicSequence)music;
|
||||
- (void (^)()) willPlaySequence:(MusicSequence)music;
|
||||
- (void) showLogAndBeep;
|
||||
|
||||
@end
|
||||
|
|
|
@ -77,6 +77,8 @@
|
|||
soundStopObserver = [nc addObserverForName:(NSString*)kVLSoundStoppedNotification
|
||||
object:nil queue:oq usingBlock:^(NSNotification *note) {
|
||||
[[[self window] toolbar] validateVisibleItems];
|
||||
if (VLSoundOut::Instance()->AtBeginning())
|
||||
[self setEditTarget:nil]; // Kill note cursor if we ran to end
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
|
@ -96,8 +98,10 @@
|
|||
|
||||
- (void)setEditTarget:(VLEditable *)editable
|
||||
{
|
||||
[editTarget autorelease];
|
||||
editTarget = editable;
|
||||
if (editTarget != editable) {
|
||||
[editTarget release];
|
||||
editTarget = editable;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) startAnimation
|
||||
|
@ -125,9 +129,9 @@
|
|||
[sheetView mouseMoved:event];
|
||||
}
|
||||
|
||||
- (void) willPlaySequence:(MusicSequence)music
|
||||
- (void (^)()) willPlaySequence:(MusicSequence)music
|
||||
{
|
||||
[sheetView willPlaySequence:music];
|
||||
return [sheetView willPlaySequence:music];
|
||||
}
|
||||
|
||||
- (IBAction) togglePlayElements:(id)sender
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
#include "VLSoundOut.h"
|
||||
#include "VLMIDIWriter.h"
|
||||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
|
@ -31,9 +32,12 @@ public:
|
|||
virtual void PlayNote(const VLNote & note);
|
||||
virtual void PlayChord(const VLChord & chord);
|
||||
virtual void PlaySequence(MusicSequence music);
|
||||
virtual void SetStart(MusicTimeStamp start);
|
||||
virtual void SetEnd(MusicTimeStamp end);
|
||||
virtual void Stop(bool pause);
|
||||
virtual bool Playing();
|
||||
virtual bool AtEnd();
|
||||
virtual bool AtBeginning();
|
||||
virtual void SetPlayRate(float rate);
|
||||
virtual void Fwd();
|
||||
virtual void Bck();
|
||||
|
@ -47,16 +51,16 @@ protected:
|
|||
|
||||
void InitSoundOutput(bool fileOutput);
|
||||
virtual void SetupOutput(AUNode outputNode);
|
||||
MusicTimeStamp SequenceLength(MusicSequence music);
|
||||
void SkipTimeInterval();
|
||||
|
||||
AUGraph fGraph;
|
||||
MusicPlayer fPlayer;
|
||||
private:
|
||||
MusicSequence fMusic;
|
||||
MusicTimeStamp fMusicLength;
|
||||
MusicTimeStamp fMusicEnd;
|
||||
bool fRunning;
|
||||
bool fForward;
|
||||
bool fWasAtEnd;
|
||||
float fPlayRate;
|
||||
dispatch_source_t fMusicPoll;
|
||||
|
||||
|
@ -157,7 +161,7 @@ VLSoundOut::~VLSoundOut()
|
|||
}
|
||||
|
||||
VLAUSoundOut::VLAUSoundOut()
|
||||
: fMusic(0), fRunning(false), fForward(true)
|
||||
: fMusic(0), fRunning(false), fForward(true), fWasAtEnd(true)
|
||||
{
|
||||
InitSoundOutput(false);
|
||||
fMusicPoll = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
|
||||
|
@ -245,8 +249,9 @@ void VLAUSoundOut::PlaySequence(MusicSequence music)
|
|||
Stop(false);
|
||||
|
||||
fMusic = music;
|
||||
fMusicLength = SequenceLength(music);
|
||||
fMusicEnd = VLMIDIUtilities(music).Length();
|
||||
fPlayRate = 1.0;
|
||||
fWasAtEnd = true;
|
||||
|
||||
R(MusicSequenceSetAUGraph(fMusic, fGraph));
|
||||
R(MusicPlayerSetSequence(fPlayer, fMusic));
|
||||
|
@ -256,7 +261,19 @@ void VLAUSoundOut::PlaySequence(MusicSequence music)
|
|||
fRunning = true;
|
||||
CFNotificationCenterPostNotification(CFNotificationCenterGetLocalCenter(), kVLSoundStartedNotification,
|
||||
NULL, NULL, false);
|
||||
dispatch_source_set_timer(fMusicPoll, DISPATCH_TIME_NOW, 500*NSEC_PER_MSEC, 200*NSEC_PER_MSEC);
|
||||
dispatch_source_set_timer(fMusicPoll, DISPATCH_TIME_NOW, 10*NSEC_PER_MSEC, 200*NSEC_PER_MSEC);
|
||||
}
|
||||
|
||||
void VLAUSoundOut::SetStart(MusicTimeStamp start)
|
||||
{
|
||||
if (fWasAtEnd)
|
||||
MusicPlayerSetTime(fPlayer, start);
|
||||
}
|
||||
|
||||
void VLAUSoundOut::SetEnd(MusicTimeStamp end)
|
||||
{
|
||||
if (fWasAtEnd)
|
||||
fMusicEnd = end;
|
||||
}
|
||||
|
||||
void VLAUSoundOut::SetMelodyState(VLSoundOut::MelodyState state)
|
||||
|
@ -282,7 +299,7 @@ void VLAUSoundOut::SetPlayRate(float rate)
|
|||
MusicTimeStamp rightNow;
|
||||
MusicPlayerGetTime(fPlayer, &rightNow);
|
||||
MusicSequenceReverse(fMusic);
|
||||
MusicPlayerSetTime(fPlayer, fMusicLength - rightNow);
|
||||
MusicPlayerSetTime(fPlayer, fMusicEnd - rightNow);
|
||||
}
|
||||
fPlayRate = fabsf(rate);
|
||||
MusicPlayerSetPlayRateScalar(fPlayer, fPlayRate);
|
||||
|
@ -343,8 +360,12 @@ void VLAUSoundOut::Slow(float rate)
|
|||
|
||||
void VLAUSoundOut::Stop(bool pause)
|
||||
{
|
||||
if (!fRunning)
|
||||
return;
|
||||
|
||||
MusicPlayerStop(fPlayer);
|
||||
fRunning = false;
|
||||
fWasAtEnd = false;
|
||||
if (!pause && fMusic) {
|
||||
MusicPlayerSetSequence(fPlayer, NULL);
|
||||
DisposeMusicSequence(fMusic);
|
||||
|
@ -364,7 +385,14 @@ bool VLAUSoundOut::AtEnd()
|
|||
{
|
||||
MusicTimeStamp time;
|
||||
|
||||
return !MusicPlayerGetTime(fPlayer, &time) && time >= fMusicLength;
|
||||
return !MusicPlayerGetTime(fPlayer, &time) && time >= fMusicEnd;
|
||||
}
|
||||
|
||||
bool VLAUSoundOut::AtBeginning()
|
||||
{
|
||||
MusicTimeStamp time;
|
||||
|
||||
return MusicPlayerGetTime(fPlayer, &time) || !time;
|
||||
}
|
||||
|
||||
void VLAUSoundOut::PollMusic()
|
||||
|
@ -372,6 +400,7 @@ void VLAUSoundOut::PollMusic()
|
|||
if (fRunning && AtEnd()) {
|
||||
MusicPlayerSetTime(fPlayer, 0);
|
||||
Stop(true);
|
||||
fWasAtEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,23 +441,6 @@ void VLAUSoundOut::Play(const int8_t * note, size_t numNotes)
|
|||
PlaySequence(music);
|
||||
}
|
||||
|
||||
MusicTimeStamp VLAUSoundOut::SequenceLength(MusicSequence music)
|
||||
{
|
||||
UInt32 ntracks;
|
||||
MusicSequenceGetTrackCount(music, &ntracks);
|
||||
MusicTimeStamp sequenceLength = 0;
|
||||
for (UInt32 i = 0; i < ntracks; ++i) {
|
||||
MusicTrack track;
|
||||
MusicTimeStamp trackLength;
|
||||
UInt32 propsize = sizeof(MusicTimeStamp);
|
||||
MusicSequenceGetIndTrack(music, i, &track);
|
||||
MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
|
||||
&trackLength, &propsize);
|
||||
sequenceLength = std::max(sequenceLength, trackLength);
|
||||
}
|
||||
return sequenceLength;
|
||||
}
|
||||
|
||||
VLAUFileSoundOut::VLAUFileSoundOut(CFURLRef file, OSType dataFormat)
|
||||
: VLAUSoundOut(true), fFile(file), fDataFormat(dataFormat)
|
||||
{
|
||||
|
@ -459,7 +471,7 @@ void VLAUFileSoundOut::PlaySequence(MusicSequence music)
|
|||
|
||||
UInt32 size;
|
||||
UInt32 numFrames = 512;
|
||||
MusicTimeStamp musicLen = SequenceLength(music)+8;
|
||||
MusicTimeStamp musicLen = VLMIDIUtilities(music).Length()+8;
|
||||
CFStringRef name =
|
||||
CFURLCopyLastPathComponent(fFile);
|
||||
CAAudioFileFormats * formats = CAAudioFileFormats::Instance();
|
||||
|
|
|
@ -42,9 +42,12 @@ public:
|
|||
virtual void PlayChord(const VLChord & chord) = 0;
|
||||
void PlayFile(CFDataRef file);
|
||||
virtual void PlaySequence(MusicSequence music) = 0;
|
||||
virtual void SetStart(MusicTimeStamp start) = 0;
|
||||
virtual void SetEnd(MusicTimeStamp end) = 0;
|
||||
virtual void Stop(bool pause=true) = 0;
|
||||
virtual bool Playing() = 0;
|
||||
virtual bool AtEnd() = 0;
|
||||
virtual bool AtBeginning() = 0;
|
||||
virtual void SetPlayRate(float rate) = 0;
|
||||
virtual void Fwd() = 0;
|
||||
virtual void Bck() = 0;
|
||||
|
|
Loading…
Reference in New Issue
Block a user