//
//  OutputAudioUnit.h
//  TapeDeck
//
//  Created by Christopher Liscio on 4/7/08.
//  Copyright 2008 SuperMegaUltraGroovy. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <SMUGAudio/SVocalRemover.h>
#import <Accelerate/Accelerate.h>
#import <CapoKit/CapoNoteEntryPlaybackStorage.h>
#import <SMUGAudio/SQueueableAudioNotification.h>
#import <SMUGAudio/SAudioNotificationQueueWorker.h>
#import <SMUGAudio/SMUGAudioBufferQueue.h>
#import "CapoSpectrumManager.h"

@class SMUGAudioStreamBasicDescription;
@class SMUGAudioBuffer;
@class SMUGVocalReductionEffectSettings;
@class SMUGEqualizerSettings;
@class CapoNoteEntryStorage;
@class CapoSpectrumData;
@class SMUGAudioBufferQueue;
@class SMUGRealVector;
@class CapoMetronomeInstrument;

@interface CapoOutputAudioUnit : NSObject <CapoSpectrumManager> {
    SMUGAudioStreamBasicDescription *mStreamDescription;
    id __weak mDelegate;
    AUGraph mGraph;
    AudioUnit mOutputUnit;
    AudioUnit mMixerUnit;
    AUNode mOutputNode;
    AUNode mMixerNode;
    AUNode mGraphicEQNode;
    AUNode mSamplerNode;
    
    BOOL mCancelExport;
    CapoNoteEntryStorage *mNoteEntryStorage;
    CapoMetronomeInstrument *mMetronomeInstrument;
    
@public
    BOOL mMIDIOutputEnabled;
    BOOL mMetronomeEnabled;
    BOOL mMetronomeAccentsDownbeat;
    AudioUnit mSamplerUnit;
    CapoPlaybackNoteEntry *mPlaybackEntries;
    CapoNoteEntryPlaybackStorage *mNoteEntryPlaybackStorage;

    AudioUnit mGraphicEQUnit;
    
    SMUGAudioBufferQueue *mAudioBufferQueue;
    SQueueableAudioNotificationRef mEndOfStreamNotification;
    SAudioNotificationQueueWorkerRef mAudioNotificationQueueWorker;
    BOOL mDone;

    BOOL mPreroll;
    int64_t mPrerollSampleStart;

    volatile int32_t mInsertingNoise;
    volatile int32_t mNoisyOutput;
    volatile int32_t mTotalOutputSampleCount;
    
    SMUGVocalReductionEffectSettings *mVocalReductionEffectSettings;
    CapoSpectrumData *mSpectrumData;
    
    SVocalRemoverRef mVocalRemover;
    
    BOOL mEnablePanAdjust;
    BOOL mOutOfPhase;
    double mPanAmount;    
    
    BOOL mExportingAudio;
    BOOL mEqualizerEnabled;
    SMUGEqualizerSettings *mEqualizerSettings;
    
    void *mDirac;
    AudioBufferList *mDiracBufferList;
    AudioBufferList *mFXBufferList;
}

@property (nonatomic, readonly,strong) SMUGAudioStreamBasicDescription *streamDescription;
@property (nonatomic, readwrite,weak) id delegate;

// Metronome
@property(nonatomic, assign,getter=isMetronomeEnabled) BOOL metronomeEnabled;
@property(nonatomic, assign) BOOL metronomeAccentsDownbeat;
@property(nonatomic, strong) CapoMetronomeInstrument *metronomeInstrument;

// Playback rate adjustment.  1.0 is normal speed.
@property (nonatomic, readwrite,assign) CGFloat playbackRate;

// Playback pitch adjustment, in cents
@property (nonatomic, readwrite,assign) CGFloat playbackPitch;

// Vocal Reduction
@property (nonatomic, readwrite,assign) BOOL removeVocals;
@property (nonatomic, readwrite,strong) SMUGVocalReductionEffectSettings *vocalReductionEffectSettings;

// Panning Adjust
@property (nonatomic, readwrite,assign) BOOL panAdjust;
@property (nonatomic, readwrite,assign) double panAmount;
@property (nonatomic, readwrite,assign) BOOL outOfPhase;

// Equalizer
@property (nonatomic, readwrite,assign) BOOL equalizerEnabled;
@property (nonatomic, readwrite,strong) SMUGEqualizerSettings *equalizerSettings;

// Current noise insertion state
@property (nonatomic, readonly,assign,getter=isInsertingNoise) BOOL insertingNoise;
@property (nonatomic, readonly,assign) SInt64 remainingNoiseFreeSamples;

@property (nonatomic, readwrite,strong) CapoNoteEntryStorage *noteEntryStorage;

@property (nonatomic, readwrite,assign) float noteEntryPlaybackLevel;

@property (nonatomic, readonly,assign) SInt64 processingLatency;

@property (nonatomic, readwrite,assign) int64_t prerollSampleStart;
@property (nonatomic, readwrite,assign) BOOL preroll;

- (void)setEndOfStreamNotificationBlock:(SQueueableAudioNotificationProcessBlock)inBlock;

@property (nonatomic, readwrite,strong) SMUGAudioBufferQueue *audioBufferQueue;

- (id)initWithStreamDescription:(SMUGAudioStreamBasicDescription*)sd forEffects:(BOOL)forEffects;

- (void)start;
- (void)stop;
- (BOOL)isRunning;

- (void)setPlaybackLevel:(CGFloat)level;
- (void)setNoisyOutput:(BOOL)noisyOutput;

- (void)writeSamples:(SInt32)duration toFileURL:(NSURL*)fileURL;
- (void)refreshNoteEntryPlaybackStorage;
- (void)cancelWriteToFile;

@end

@interface NSObject(CapoOutputAudioUnitDelegate)
- (void)outputAudioUnit:(CapoOutputAudioUnit*)au didUpdateProgress:(NSNumber*)progress;
@end
