Fixed double headers in some files
[camargo/neiasound.git] / src / sndfile / nSndfileStream.cpp
1 // Copyright (C) 2015 Lucas Pires Camargo
2 // 
3 // This file is part of neiasound - Qt-style OpenAL wrapper for games.
4 // 
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 // 
9 // 1. Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // 
12 // 2. Redistributions in binary form must reproduce the above copyright notice,
13 // this list of conditions and the following disclaimer in the documentation
14 // and/or other materials provided with the distribution.
15 // 
16 // THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS
17 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 // NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include "nSndfileStream.h"
28 #include "sndfile.h"
29 #include <cstdio>
30 #include <QDataStream>
31 #include "../nSoundBag.h"
32
33 // SF_VIRTUAL_IO handler functions
34
35 sf_count_t nSndfileStream_vio_filelen(void * userData)
36 {
37     QIODevice * device = ((QIODevice*)userData);
38     sf_count_t size = device->size();
39     return size;
40 }
41
42 sf_count_t nSndfileStream_vio_seek(sf_count_t offset, int whence, void * userData)
43 {
44     QIODevice * device = ((QIODevice*)userData);
45     switch(whence)
46     {
47     case SEEK_SET:
48         device->seek(offset);
49         return 0;
50
51     case SEEK_CUR:
52         device->seek(device->pos()+offset);
53         return 0;
54
55     case SEEK_END:
56         device->seek(device->size()-offset);
57         return 0;
58     }
59
60     return -1;
61 }
62
63 sf_count_t nSndfileStream_vio_read(void * ptr, sf_count_t count, void * userData)
64 {
65     QIODevice * device = ((QIODevice*)userData);
66     return device->read((char*)ptr, count);
67 }
68
69 sf_count_t nSndfileStream_vio_write(const void * ptr, sf_count_t count, void * userData)
70 {
71     // WRITING UNSUPPORTED
72     return -1;
73 }
74
75 sf_count_t nSndfileStream_vio_tell(void * userData)
76 {
77     QIODevice * device = ((QIODevice*)userData);
78     sf_count_t pos = device->pos();
79     return pos;
80 }
81
82
83
84
85
86
87 // ------------------------
88 // class nSndfileStream
89 // ------------------------
90
91 nSndfileStream::nSndfileStream(QString filename, QObject * parent)
92     :nSoundStream(parent)
93 {
94     m_iodevice = 0;
95     m_ownsDevice = false;
96     m_virtualio = 0;
97     m_sndinfo = new SF_INFO();
98     ((SF_INFO*)m_sndinfo)->format = 0;
99
100     m_sndfile = sf_open(filename.toLocal8Bit(), SFM_READ, (SF_INFO*)m_sndinfo);
101     if(!m_sndfile)
102         throw QString("nSndfileStream::nSndfileStream(QString): Failed to open file: ")+filename;
103
104     fillInfo();
105 }
106
107 nSndfileStream::nSndfileStream(QIODevice * device, QObject * parent, bool ownsDevice)
108     :nSoundStream(parent), m_ownsDevice(ownsDevice)
109 {
110     m_iodevice = device;
111     if(!m_iodevice->isOpen())
112         if(!m_iodevice->open(QIODevice::ReadOnly))
113             throw QString("nSndfileStream::nSndfileStream(QIODevice*): Failed to open device for reading.");
114
115     m_sndinfo = new SF_INFO();
116     ((SF_INFO*)m_sndinfo)->format = 0;
117     m_virtualio = new SF_VIRTUAL_IO();
118
119     //setup function pointers
120     SF_VIRTUAL_IO & vio = *((SF_VIRTUAL_IO*)m_virtualio);
121     vio.get_filelen = nSndfileStream_vio_filelen;
122     vio.read = nSndfileStream_vio_read;
123     vio.write = nSndfileStream_vio_write;
124     vio.seek = nSndfileStream_vio_seek;
125     vio.tell = nSndfileStream_vio_tell;
126
127     m_sndfile = sf_open_virtual((SF_VIRTUAL_IO*)m_virtualio, SFM_READ, (SF_INFO*)m_sndinfo, m_iodevice);
128
129     if(!m_sndfile)
130         throw QString("nSndfileStream::nSndfileStream(OgreStreamEtc...): Failed to open virtual stream.");
131
132     fillInfo();
133 }
134
135 nSndfileStream::~nSndfileStream()
136 {
137     if(m_virtualio) delete ((SF_VIRTUAL_IO*)m_virtualio);
138
139     sf_close((SNDFILE*)m_sndfile);
140     delete m_sndinfo;
141
142     if(m_ownsDevice && m_iodevice)
143         delete m_iodevice;
144 }
145
146 nSoundBag * nSndfileStream::createSoundBag(QObject * parent)
147 {
148     nSoundBag * bag = new nSoundBag(format(), m_info_frames, m_info_samplerate, parent);
149     read(bag->m_data, m_info_frames);
150     return bag;
151 }
152
153 void nSndfileStream::fillInfo()
154 {
155     m_info_frames = (((SF_INFO*)(m_sndinfo)))->frames;
156     m_info_format = (((SF_INFO*)(m_sndinfo)))->format;
157     m_info_samplerate = (((SF_INFO*)(m_sndinfo)))->samplerate;
158     m_info_channels = (((SF_INFO*)(m_sndinfo)))->channels;
159     // nLog::defaultLog(QString("nSndFileStream: Created new stream, %1 frames, %2hz, %3s, %4 channels.").arg(m_info_frames).arg(m_info_samplerate).arg(((double)m_info_frames)/m_info_samplerate).arg(m_info_channels), nLog::LL_WHOGIVESAFUCKANYWAY);
160
161 }
162
163 nSoundFormat nSndfileStream::format()
164 {
165     if(m_info_channels==1)
166         return SF_16BIT_MONO;
167
168     if(m_info_channels==2)
169         return SF_16BIT_STEREO;
170
171     return SF_UNDEFINED;
172 }
173
174 bool nSndfileStream::suggestStreaming()
175 {
176     if( ((m_info_format & SF_FORMAT_VORBIS) != 0) || (m_info_frames > m_info_samplerate*5))
177         return true; //suggest stream if ogg vorbis or if larger than 5 seconds
178 }
179
180
181 void nSndfileStream::rewind()
182 {
183     sf_seek((SNDFILE*)m_sndfile, 0, SEEK_SET);
184 }
185
186 quint64 nSndfileStream::read(void* data, unsigned long frames)
187 {
188     return sf_readf_short((SNDFILE*)m_sndfile, (short*)data, frames);
189 }