kwave  18.07.70
Writer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  Writer.cpp - base class for writers, providing a C++ stream interface
3  -------------------
4  begin : Sun Aug 23 2009
5  copyright : (C) 2009 by Thomas Eschenbacher
6  email : Thomas Eschenbacher <thomas.eschenbacher@gmx.de>
7 
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "config.h"
20 
21 #include <QObject>
22 
23 #include "libkwave/SampleReader.h"
24 #include "libkwave/Utils.h"
25 #include "libkwave/Writer.h"
26 #include "libkwave/memcpy.h"
27 
29 #define BUFFER_SIZE (1024 * 1024)
30 
32 #define MIN_DIRECT_IO_BLOCK_SIZE (BUFFER_SIZE / 2)
33 
34 //***************************************************************************
36  :Kwave::SampleSink(Q_NULLPTR),
37  m_first(0), m_last(0), m_mode(Kwave::Insert), m_position(0),
38  m_buffer(BUFFER_SIZE), m_buffer_size(BUFFER_SIZE), m_buffer_used(0)
39 {
40 }
41 
42 //***************************************************************************
44  sample_index_t left, sample_index_t right)
45  :Kwave::SampleSink(Q_NULLPTR),
46  m_first(left), m_last(right), m_mode(mode), m_position(left),
48 {
49 }
50 
51 //***************************************************************************
53 {
54  // If this assert gets hit, you deleted a writer without calling
55  // flush() before. Flushing in the destructor is problematic and
56  // might be too late when the derived classes' destructor was
57  // already done and signal/slot connections were already released!
58  Q_ASSERT(!m_buffer_used);
59  if (m_buffer_used) qWarning("Writer was not flushed!?");
60 
61  Q_ASSERT((m_mode != Kwave::Overwrite) || (m_position <= m_last + 1));
62 
63  // inform others that we proceeded
65 }
66 
67 //***************************************************************************
69 {
70  unsigned int count = samples.size();
71 
72  if ( (m_buffer_used || (count < MIN_DIRECT_IO_BLOCK_SIZE)) &&
73  (m_buffer_used + count <= m_buffer_size) )
74  {
75  // append to the internal buffer if it is already in use
76  // and if there is still some room,
77  // or if the buffer so small that it would make too much overhead
78  // to process it by block operation
79  MEMCPY(&(m_buffer[m_buffer_used]), &(samples[0]),
80  count * sizeof(sample_t));
81  m_buffer_used += count;
82  if (m_buffer_used >= m_buffer_size) flush();
83  } else {
84  // first flush the single-sample buffer before doing block operation
85  if (m_buffer_used) flush();
86 
87  // now flush the block that we received as parameter (pass-through)
88  write(samples, count);
89  Q_ASSERT(!count);
90  }
91 
92  return *this;
93 }
94 
95 //***************************************************************************
97 {
98  m_buffer[m_buffer_used++] = sample;
100  return *this;
101 }
102 
103 //***************************************************************************
105 {
106  if (m_buffer_used) flush();
107 
108  // transfer data, using our internal buffer
109  unsigned int buflen = m_buffer_size;
110  while (!reader.eof() && !eof()) {
111 
112  // overwrite mode -> clip at right border
113  if (m_mode == Kwave::Overwrite) {
114  if (m_position + buflen - 1 > m_last)
115  buflen = Kwave::toUint(m_last - m_position + 1);
116  }
117 
118  m_buffer_used = reader.read(m_buffer, 0, buflen);
119  Q_ASSERT(m_buffer_used);
120  if (!m_buffer_used) break;
121 
122  if (!flush()) return *this; // out of memory
123  }
124 
125  // pad the rest with zeroes
126  if (m_mode == Kwave::Overwrite) {
127  Q_ASSERT(m_position <= m_last + 1);
128  while (m_buffer_used + m_position <= m_last) {
129  *this << static_cast<sample_t>(0);
130  m_position++;
131  }
132  Q_ASSERT(m_position <= m_last + 1);
133  }
134 
135  return *this;
136 }
137 
138 //***************************************************************************
139 bool Kwave::Writer::eof() const
140 {
141  return (m_mode == Kwave::Overwrite) ? (m_position > m_last) : false;
142 }
143 
144 //***************************************************************************
146 {
147  s.flush();
148  return s;
149 }
150 
151 //***************************************************************************
153 {
154  if (data.size()) (*this) << data;
155 }
156 
157 //***************************************************************************
158 //***************************************************************************
#define MIN_DIRECT_IO_BLOCK_SIZE
Definition: Writer.cpp:32
virtual bool write(const Kwave::SampleArray &buffer, unsigned int &count)=0
Definition: App.h:33
virtual bool eof() const
Definition: Writer.cpp:139
bool flush()
Definition: Writer.h:94
void sigSamplesWritten(sample_index_t)
quint64 sample_index_t
Definition: Sample.h:28
Kwave::SampleArray m_buffer
Definition: Writer.h:161
sample_index_t m_first
Definition: Writer.h:149
bool eof() const
Definition: SampleReader.h:66
unsigned int m_buffer_used
Definition: Writer.h:167
#define MEMCPY
Definition: memcpy.h:37
virtual ~Writer() Q_DECL_OVERRIDE
Definition: Writer.cpp:52
sample_index_t m_last
Definition: Writer.h:152
sample_index_t m_position
Definition: Writer.h:158
void input(Kwave::SampleArray data)
Definition: Writer.cpp:152
virtual Writer & operator<<(const Kwave::SampleArray &samples)
Definition: Writer.cpp:68
#define BUFFER_SIZE
Definition: Writer.cpp:29
unsigned int size() const
unsigned int read(Kwave::SampleArray &buffer, unsigned int dstoff, unsigned int length)
unsigned int toUint(T x)
Definition: Utils.h:109
InsertMode
Definition: InsertMode.h:26
unsigned int m_buffer_size
Definition: Writer.h:164
Kwave::InsertMode mode() const
Definition: Writer.h:125
Kwave::InsertMode m_mode
Definition: Writer.h:155
qint32 sample_t
Definition: Sample.h:37