summaryrefslogtreecommitdiff
path: root/libs/ardour/caimportable.cc
blob: e78691a1dd41621cdb27723b83107ca6390c8b64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "ardour/caimportable.h"
#include <sndfile.h>
#include "pbd/error.h"

#include "i18n.h"

using namespace ARDOUR;
using namespace std;
using namespace PBD;

CAImportableSource::CAImportableSource (const string& path)
{
	try {
		af.Open (path.c_str());

		CAStreamBasicDescription file_format (af.GetFileDataFormat());
		CAStreamBasicDescription client_format (file_format);

		/* set canonial form (PCM, native float packed, 32 bit, with the correct number of channels
		   and interleaved (since we plan to deinterleave ourselves)
		*/

		client_format.SetCanonical(client_format.NumberChannels(), true);
		af.SetClientFormat (client_format);

	} catch (CAXException& cax) {
                //Don't report an error here since there is one higher up in import.
                //Since libsndfile gets tried second, any failures here may show as
                //invalid errors in the Error log.
		throw failed_constructor ();
	}

}

CAImportableSource::~CAImportableSource ()
{
}

nframes_t
CAImportableSource::read (Sample* buffer, nframes_t nframes)
{
	nframes_t nread = 0;
	AudioBufferList abl;
	nframes_t per_channel;
	bool at_end = false;

	abl.mNumberBuffers = 1;
	abl.mBuffers[0].mNumberChannels = channels();

	per_channel = nframes / abl.mBuffers[0].mNumberChannels;

	while (nread < per_channel) {

		UInt32 new_cnt = per_channel - nread;

		abl.mBuffers[0].mDataByteSize = new_cnt * abl.mBuffers[0].mNumberChannels * sizeof(Sample);
		abl.mBuffers[0].mData = buffer + nread;

		try {
			af.Read (new_cnt, &abl);
		} catch (CAXException& cax) {
			error << string_compose("CAImportable: %1", cax.mOperation);
			return -1;
		}

		if (new_cnt == 0) {
			/* EOF */
			at_end = true;
			break;
		}

		nread += new_cnt;
	}

	if (!at_end && nread < per_channel) {
		return 0;
	} else {
		return nread * abl.mBuffers[0].mNumberChannels;
	}
}

uint
CAImportableSource::channels () const
{
	return af.GetFileDataFormat().NumberChannels();
}

framecnt_t
CAImportableSource::length () const
{
	return af.GetNumberFrames();
}

nframes_t
CAImportableSource::samplerate() const
{
	CAStreamBasicDescription client_asbd;

	try {
		client_asbd = af.GetClientDataFormat ();
	} catch (CAXException& cax) {
		error << string_compose ("CAImportable: %1", cax.mOperation) << endmsg;
		return 0.0;
	}

	return client_asbd.mSampleRate;
}

void
CAImportableSource::seek (nframes_t pos)
{
	try {
		af.Seek (pos);
	} catch (CAXException& cax) {
		error << string_compose ("CAImportable: %1 to %2", cax.mOperation, pos) << endmsg;
	}
}