// // MetronomeManager.m // KulexiuSchoolStudent // // Created by 王智 on 2023/7/24. // #import "MetronomeManager.h" #import #import "RhythmChooseView.h" @interface MetronomeManager () /** 定时器 */ @property (nonatomic, strong) NSTimer *timer; /** 定时器多少秒循环一次 */ @property (nonatomic, assign) double timerLength; @property (nonatomic, assign) int currentNo; @property (nonatomic, assign) NSInteger lastChooseIndex; @end @implementation MetronomeManager + (instancetype)shareInstance { static MetronomeManager *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [[MetronomeManager alloc] init]; }); return manager; } - (instancetype)init { self = [super init]; if (self) { [self configDefault]; } return self; } - (void)configDefault { self.speed = 90; self.rhythmType = RHYTHM_TYPE_ONE_QUARTERNOTES; self.timerLength = 60.0 / (1.0 * self.speed) / ([self getRate]); [self resetTimerPlay]; [self createPlayer]; self.playVolume = 1.0f; self.beatNumber = 4; self.lastChooseIndex = 4; } - (void)setPlayVolume:(float)playVolume { _playVolume = playVolume; self.player.volume = playVolume; } #pragma mark ---- delegate - (void)metronomePlayInterruption { if (self.isPlaying) { [self stopPlay]; } } - (void)startPlay { if (self.isPlaying == NO) { // 重置 self.currentNo = -1; // int bpm = self.speed * [self getRate]; [self.player playRhythmAction:self.speed rhythmType:self.rhythmType beatNumber:self.beatNumber]; // 开始播放 [self.timer setFireDate:[NSDate distantPast]]; } self.isPlaying = YES; } - (void)stopPlay { if (self.isPlaying) { self.isPlaying = NO; [self.timer setFireDate:[NSDate distantFuture]];//暂停计时器 self.currentNo = -1; [self.player stopPlay]; } } - (void)setSpeed:(int)speed { _speed = speed; int rateFloat = speed; self.timerLength = 60.0 / (1.0 * rateFloat) / ([self getRate]); NSLog(@"---- %f",self.self.timerLength); [self resetTimerPlay]; if (self.isPlaying) { [self stopPlay]; [self startPlay]; } } - (CGFloat)getRate { return 1.0; } - (void)resetTimerPlay { if (_timer) { [self resetTimer]; MJWeakSelf; _timer = [NSTimer scheduledTimerWithTimeInterval:self.timerLength repeats:YES block:^(NSTimer * _Nonnull timer) { [weakSelf timerAction]; }]; [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; [_timer setFireDate:[NSDate distantFuture]]; } } - (NSTimer *)timer{ if (!_timer) { MJWeakSelf; _timer = [NSTimer scheduledTimerWithTimeInterval:self.timerLength repeats:YES block:^(NSTimer * _Nonnull timer) { [weakSelf timerAction]; }]; [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; [_timer setFireDate:[NSDate distantFuture]]; } return _timer; } - (void)timerAction { [self updateStep]; } - (void)updateStep { NSLog(@"---- current no ------ %d ", self.currentNo); self.currentNo++; // 通知刷新 if (self.delegate && [self.delegate respondsToSelector:@selector(updateSpotHightState:)]) { [self.delegate updateSpotHightState:self.currentNo]; } } #pragma mark -- 重置定时器 - (void)resetTimer{ [self.timer setFireDate:[NSDate distantPast]]; [_timer invalidate]; _timer = nil; } - (void)removeAll{ if (_timer) { [_timer invalidate]; _timer = nil; } } - (void)createPlayer { self.player = [[KSMetronomePlayer alloc] init]; self.player.delegate = self; } - (void)freePlayer { [self removeAll]; if (self.player.isPlaying) { [self.player stopPlay]; } _player = nil; } - (NSString *)getTypeString { return [NSString stringWithFormat:@"%zd", self.beatNumber]; } - (void)beatChooseCallback:(BeatChangeCallback)callback { KSChoosePicker *pickerView = [[KSChoosePicker alloc] initWithTitle:@"节拍" sourceData:@[@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"] lastChooseIndex:self.lastChooseIndex sureButtonColor:HexRGB(0x1CACF1) chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) { self.lastChooseIndex = chooseIndex; NSInteger beatNumber = [returnValue integerValue]; self.beatNumber = beatNumber; [self changeBeat]; [self resetRyhthm]; if (callback) { callback(beatNumber); } } cancel:^{ }]; [pickerView showPicker]; } - (void)resetRyhthm { self.rhythmType = RHYTHM_TYPE_ONE_QUARTERNOTES; } - (void)rhythmChooseCallback:(RhythmChangeCallback)callback { RhythmChooseView *chooseView = [RhythmChooseView shareInstance]; [chooseView configWithRhythmChooseViewWithPreChoose:METRONOME_MANAGER.rhythmType displayView:[NSObject getKeyWindow]]; [chooseView chooseCallback:^(RHYTHM_TYPE type) { self.rhythmType = type; [self changeBeat]; if (callback) { callback(type); } }]; } - (void)changeBeat { self.timerLength = 60.0 / (1.0 * self.speed) / ([self getRate]); [self resetTimerPlay]; [self stopPlay]; } - (NSString *)imageWithType:(RHYTHM_TYPE)type { NSInteger index = type; NSArray *array = @[@"rhythm_quarterNote",@"rhythm_two_eighthNote",@"rhythm_quarter_riplet",@"rhythm_four_sixteenthNote",@"rhythm_quarter_and_eighth_riplet",@"rhythm_dottedEighth_and_sixteenthNote",@"rhythm_eighth_and_two_sixteenthNote"]; return array[index]; } - (void)resetDefaultConfig { [self configDefault]; } @end