To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / CollidoscopeApp / include / BufferToWaveRecorderNode.h

History | View | Annotate | Download (6.43 KB)

1
/*
2

3
 Copyright (C) 2016  Queen Mary University of London 
4
 Author: Fiore Martin
5

6
 This file is part of Collidoscope.
7
 
8
 Collidoscope is free software: you can redistribute it and/or modify
9
 it under the terms of the GNU General Public License as published by
10
 the Free Software Foundation, either version 3 of the License, or
11
 (at your option) any later version.
12

13
 This program is distributed in the hope that it will be useful,
14
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 GNU General Public License for more details.
17

18
 You should have received a copy of the GNU General Public License
19
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20

21
 This file incorporates work covered by the following copyright and permission notice: 
22

23
    Copyright (c) 2014, The Cinder Project
24

25
    This code is intended to be used with the Cinder C++ library, http://libcinder.org
26

27
    Redistribution and use in source and binary forms, with or without modification, are permitted provided that
28
    the following conditions are met:
29

30
    * Redistributions of source code must retain the above copyright notice, this list of conditions and
31
    the following disclaimer.
32
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
33
    the following disclaimer in the documentation and/or other materials provided with the distribution.
34

35
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
36
    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38
    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
39
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
    POSSIBILITY OF SUCH DAMAGE.
43
 
44
*/
45

    
46
#pragma once
47

    
48
#include "cinder/Cinder.h"
49
#include "cinder/audio/Node.h"
50
#include "cinder/audio/SampleRecorderNode.h"
51
#include "cinder/audio/dsp/RingBuffer.h"
52
#include "cinder/Filesystem.h"
53

    
54
#include "Messages.h"
55

    
56
typedef std::shared_ptr<class BufferToWaveRecorderNode> BufferToWaveRecorderNodeRef;
57

    
58
typedef ci::audio::dsp::RingBufferT<RecordWaveMsg> RecordWaveMsgRingBuffer;
59

    
60
/**
61
 * A \a Node in the audio graph of the Cinder audio library that records input in a buffer.
62
 *
63
 * This class is similar to \a cinder::audio::BufferRecorderNode (it's a derivative work of this class indeed) but it has an additional feature:
64
 * when recording, it uses the audio input samples to compute the size values of the visual chunks. 
65
 * The chunks values are stored in a ring buffer and fetched by the graphic thread to paint the wave as it gets recorded.
66
 *
67
 */
68
class BufferToWaveRecorderNode : public ci::audio::SampleRecorderNode {
69
public:
70

    
71
    static const float kRampTime;
72

    
73
    //! Constructor. numChunks is the total number of chunks this biffer has to be borken down in. 
74
    //! numSeconds lenght of the buffer in seconds 
75
    BufferToWaveRecorderNode( std::size_t numChunks, double numSeconds );
76

    
77
    //! Starts recording. Resets the write position to zero (call disable() to pause recording).
78
    void start();
79
    //! Stops recording. Same as calling disable().
80
    void stop();
81

    
82
    //! \brief Sets the length of the recording buffer in frames.
83
    //!
84
    //! If the write position is non-zero, the old contents will be preserved (by copying it to the newly allocated Buffer).
85
    //! If \a shrinkToFit is set to `true`, the internal Buffer will be down-sized if necessary, otherwise it will only re-allocate when growing while changing its dimensions to match \a numFrames (default shrinkToFit = false).
86
    void setNumFrames(size_t numFrames, bool shrinkToFit = false);
87
    //! Sets the length of the recording buffer in seconds. \see setNumFrames
88
    void setNumSeconds(double numSeconds, bool shrinkToFit = false);
89

    
90
    //! Returns the length of the recording buffer in frames.
91
    size_t      getNumFrames() const    { return mRecorderBuffer.getNumFrames(); }
92
    //! Returns the length of the recording buffer in seconds.
93
    double      getNumSeconds() const;
94

    
95
    //! \brief Returns a copy of the recored samples, up to the current write position.
96
    //!
97
    //! This method is non locking, and as such any resizing calls must be performed on the same thread or be otherwise synchronized.
98
    ci::audio::BufferRef    getRecordedCopy() const;
99

    
100
    //! \brief Writes the currently recorded samples to a file at \a filePath
101
    //!
102
    //! The encoding format is derived from \a filePath's extension and \a sampleType (default = SampleType::INT_16).
103
    //! \note throws AudioFileExc if the write request cannot be completed.
104
    void writeToFile(const ci::fs::path &filePath, ci::audio::SampleType sampleType = ci::audio::SampleType::INT_16);
105

    
106
    //! Returns the frame of the last buffer overrun or 0 if none since the last time this method was called. When this happens, it means the recorded buffer probably has skipped some frames.
107
    uint64_t getLastOverrun();
108

    
109
    //! returns a reference to the ring buffer when the size values of the chunks is stored, when a new wave is recorder
110
    RecordWaveMsgRingBuffer& getRingBuffer() { return mRingBuffer; }
111

    
112
    //!returns a pointer to the buffer where the audio is recorder. This is used by the PGranular to create the granular synthesis 
113
    ci::audio::Buffer* getRecorderBuffer() { return &mRecorderBuffer; }
114

    
115

    
116
protected:
117
    void initialize()               override;
118
    void process(ci::audio::Buffer *buffer) override;
119

    
120
    void initBuffers(size_t numFrames);
121

    
122
    static const float kMinAudioVal; 
123
    static const float kMaxAudioVal;
124

    
125
    ci::audio::BufferDynamic        mRecorderBuffer;
126
    ci::audio::BufferDynamicRef     mCopiedBuffer;
127
    std::atomic<uint64_t>   mLastOverrun;
128

    
129
    RecordWaveMsgRingBuffer mRingBuffer;
130

    
131
    const std::size_t mNumChunks;
132
    const double mNumSeconds;
133
    std::size_t mNumSamplesPerChunk;
134
    std::atomic<std::size_t> mChunkIndex;
135

    
136
    size_t mChunkSampleCounter;
137
    float mChunkMaxAudioVal;
138
    float mChunkMinAudioVal;
139

    
140
    float mEnvRamp;
141
    float mEnvRampRate;
142
    size_t mEnvRampLen;
143
    size_t mEnvDecayStart;
144

    
145
};
146