Architecture Error in recording demo


#1

So I am trying to build the recording demo without all the GUI components, but whenever I try compiling I keep getting this compiler error:

ld: warning: ignoring file /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks//QuickTime.framework/QuickTime.tbd, missing required architecture x86_64 in file /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks//QuickTime.framework/QuickTime.tbd
Undefined symbols for architecture x86_64:
“MainAppWindow::getSharedAudioDeviceManager()”, referenced from:
MainContentComponent::MainContentComponent() in MainComponent.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

MainComponent.cpp:

#ifndef MAINCOMPONENT_H_INCLUDED
#define MAINCOMPONENT_H_INCLUDED

#include “…/JuceLibraryCode/JuceHeader.h”
#include “MainAppWindow.h”
//==============================================================================
/*
This component lives inside our window, and this is where you should put all
your controls and content.
*/

class AudioRecorder : public AudioIODeviceCallback
{
public:
AudioRecorder(AudioThumbnail& thumbnailToUpdate)
: thumbnail (thumbnailToUpdate),
backgroundThread(“Audio Recorder Thread”),
sampleRate (0), nextSampleNum (0), activeWriter(nullptr)
{
backgroundThread.startThread();
}

~AudioRecorder()
{
    stop();
}

void beginRec (const File& file)
{
    stop();
    
    if (sampleRate > 0)
    {
        file.deleteFile();
        ScopedPointer<FileOutputStream> fileStream(file.createOutputStream());
        
        if (fileStream != nullptr)
        {
            WavAudioFormat wavFormat;
            AudioFormatWriter* writer = wavFormat.createWriterFor (fileStream, sampleRate, 1, 16, StringPairArray(), 0);
            
            if (writer != nullptr)
            {
                fileStream.release();
                
                threadedWriter = new AudioFormatWriter::ThreadedWriter
                (writer, backgroundThread, 32768);
                
                thumbnail.reset (writer->getNumChannels(), writer->getSampleRate());
                nextSampleNum = 0;
                
                const ScopedLock sl(writerLock);
                activeWriter = threadedWriter;
            }
        }
    }
}

void stop()
{
    {
        const ScopedLock sl (writerLock);
        activeWriter = nullptr;
    }
    
    threadedWriter = nullptr;
}

bool isRec() const
{
    return activeWriter != nullptr;
}
      
void audioDeviceAboutToStart (AudioIODevice* device) override
{
    sampleRate = device ->getCurrentSampleRate();
}

void audioDeviceStopped() override
{ 
    sampleRate = 0;
}

void audioDeviceIOCallback (const float** inputChannelData, int /*numInputChannels*/, float** outputChannelData, int numOutputChannels, int numSamples) override
{
    const ScopedLock sl (writerLock);
    
    if (activeWriter != nullptr)
    {
        activeWriter->write (inputChannelData, numSamples);
        
        const AudioSampleBuffer buffer(const_cast<float**> (inputChannelData), thumbnail.getNumChannels(), numSamples);
        thumbnail.addBlock (nextSampleNum, buffer, 0, numSamples);
        nextSampleNum += numSamples;
    }
    
    for (int i = 0; i < numOutputChannels; ++i)
        if(outputChannelData[i] !=nullptr)
            FloatVectorOperations::clear(outputChannelData[i], numSamples);
}

private:
AudioThumbnail& thumbnail;
TimeSliceThread backgroundThread;
ScopedPointerAudioFormatWriter::ThreadedWriter threadedWriter;
double sampleRate;
int64 nextSampleNum;

CriticalSection writerLock;
AudioFormatWriter::ThreadedWriter* volatile activeWriter;

};

class RecordingThumbnail : public Component,
private ChangeListener

{
public:
RecordingThumbnail()
:thumbnailCache(10),
thumbnail(512, formatManager, thumbnailCache),
displayFullThumb(false)
{
formatManager.registerBasicFormats();
thumbnail.addChangeListener (this);
}

~RecordingThumbnail()
{
    thumbnail.removeChangeListener (this);
}

AudioThumbnail& getAudioThumbnail()
{
    return thumbnail;
}

void setDisplayFullThumbnail(bool displayFull)
{
    displayFullThumb = displayFull;
    repaint();
}

void paint (Graphics& g) override
{
    g.fillAll (Colours::darkgrey);
    g.setColour (Colours::lightgrey);
    
    if (thumbnail.getTotalLength() > 0.0)
    {
        const double endTime = displayFullThumb ? thumbnail.getTotalLength()
        : jmax(30.0, thumbnail.getTotalLength());
        
        Rectangle<int> thumbArea (getLocalBounds());
        thumbnail.drawChannels(g, thumbArea.reduced (2), 0.0, endTime, 1.0f);
    }
    
    else
    {
        g.setFont (14.0f);
        g.drawFittedText ("(No file recorded)", getLocalBounds(), Justification::centred, 2);
    }
}

private:
    AudioFormatManager formatManager;
    AudioThumbnailCache thumbnailCache;
    AudioThumbnail thumbnail;
    bool displayFullThumb;
    
    void changeListenerCallback (ChangeBroadcaster* source) override
{
    if (source == &thumbnail)
        repaint();
}
 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RecordingThumbnail)

};

class MainContentComponent : public AudioAppComponent,
//public Component,
private Button::Listener
{
public:
//==============================================================================
MainContentComponent()

    :deviceManager(MainAppWindow::getSharedAudioDeviceManager()), recorder (recordingThumbnail.getAudioThumbnail())
{
    
    setOpaque(true);
    
    addAndMakeVisible(explanationLabel);
    explanationLabel.setText ("This page demonstrates how to record a wave file from the live audio input..\n\nPressing record will start recording a file in your \"Documents\" folder.", dontSendNotification);
    explanationLabel.setFont(Font (15.00f, Font::plain));
    explanationLabel.setJustificationType(Justification::topLeft);
    explanationLabel.setEditable(false, false, false);
    explanationLabel.setColour(TextButton::buttonColourId, Colour(0xffff5c5c));
    recordButton.setColour(TextButton::textColourOnId, Colours::black);
    
    
    setSize (800, 600);
    
    // specify the number of input and output channels that we want to open
    setAudioChannels (2, 2);
}

~MainContentComponent()
{
    shutdownAudio();
}

//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override
{
    // This function will be called when the audio device is started, or when
    // its settings (i.e. sample rate, block size, etc) are changed.

    // You can use this function to initialise any resources you might need,
    // but be careful - it will be called on the audio thread, not the GUI thread.

    // For more details, see the help for AudioProcessor::prepareToPlay()
}

void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
{
    // Your audio-processing code goes here!

    // For more details, see the help for AudioProcessor::getNextAudioBlock()

    // Right now we are not producing any data, in which case we need to clear the buffer
    // (to prevent the output of random noise)
    bufferToFill.clearActiveBufferRegion();
}

void releaseResources() override
{
    // This will be called when the audio device stops, or when it is being
    // restarted due to a setting change.

    // For more details, see the help for AudioProcessor::releaseResources()
}

//==============================================================================
void paint (Graphics& g) override
{
    // (Our component is opaque, so we must completely fill the background with a solid colour)
    g.fillAll (Colours::black);


    // You can add your drawing code here!
}

void resized() override
{
    // This is called when the MainContentComponent is resized.
    // If you add any child components, this is where you should
    // update their positions.
    
    Rectangle<int> area (getLocalBounds());
    recordButton.setBounds (area.removeFromTop(80).reduced(8));
    recordButton.setBounds (area.removeFromTop (36).removeFromLeft(140).reduced(8));
    explanationLabel.setBounds(area.reduced(8));
}

private:
//==============================================================================
AudioDeviceManager& deviceManager;
RecordingThumbnail recordingThumbnail;
AudioRecorder recorder;
Label explanationLabel;
TextButton recordButton;

// Your private member variables go here...

void beginRec()
{
    const File file (File::getSpecialLocation (File::userDocumentsDirectory)
    .getNonexistentChildFile("Juce Demo Audio Recording", ".wav"));
    recorder.beginRec (file);
    recordButton.setButtonText("Stop");
}
    

void endRec()
{
    recorder.stop();
    recordButton.setButtonText("Record");
}

void buttonClicked(Button* button) override
{
    if (button==&recordButton)
    {
        if(recorder.isRec())
            endRec();
        else 
            beginRec();
    }
}

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)

};

// (This function is called by the app startup code to create our main component)
Component* createMainContentComponent() { return new MainContentComponent(); }

#endif // MAINCOMPONENT_H_INCLUDED

MainAppWindow.h:

#ifndef MAINAPPWINDOW_H_INCLUDED
#define MAINAPPWINDOW_H_INCLUDED

class ContentComponent;

class MainAppWindow : public DocumentWindow,
private AsyncUpdater

{
public:

MainAppWindow();
~MainAppWindow();

static MainAppWindow* getMainAppWindow();

void closeButtonPressed() override;

static ApplicationCommandManager&
    getApplicationCommandManager();
    
static AudioDeviceManager& getSharedAudioDeviceManager();

StringArray getRenderingEngines() const;
int getActiveRenderingEngine() const;
void setRenderingEngine(int index);
void setOpenGLRenderingEngine();

static Path getJUCELogoPath();

enum CommandIDs
{
    showPreviousDemo            = 0x2100,
    showNextDemo                = 0x2101,

    welcome                     = 0x2000,
    componentsAnimation         = 0x2001,
    componentsDialogBoxes       = 0x2002,
    componentsKeyMappings       = 0x2003,
    componentsMDI               = 0x2004,
    componentsPropertyEditors   = 0x2005,
    componentsTransforms        = 0x2006,
    componentsWebBrowsers       = 0x2007,
    componentsWidgets           = 0x2008,

    renderingEngineOne          = 0x2300,
    renderingEngineTwo          = 0x2301,
    renderingEngineThree        = 0x2302, // these must be contiguous!

    useLookAndFeelV1            = 0x200b,
    useLookAndFeelV2            = 0x200c,
    useLookAndFeelV3            = 0x200d,

    toggleRepaintDebugging      = 0x200e,

    useNativeTitleBar           = 0x201d,
    goToKioskMode               = 0x200f
};

private:
ScopedPointer contentComponent;
ScopedPointer taskbarIcon;
ScopedPointer
currentBubbleMessage;

TooltipWindow tooltipWindow;

#if JUCE_OPENGL
OpenGLContext openGLContext;
#endif

void handleAsyncUpdate() override;
void showMessageBubble (const String&);

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainAppWindow)

};

#endif // MAINAPPWINDOW_H_INCLUDED

Has anyone ran into this error before?