~ubuntu-branches/ubuntu/karmic/gst-plugins-bad0.10/karmic-proposed

« back to all changes in this revision

Viewing changes to gst/modplug/libmodplug/load_mtm.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-04-29 09:44:58 UTC
  • mto: (17.1.2 gutsy) (18.2.1 squeeze) (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20060429094458-rv7x6chzq7e43c8y
Tags: upstream-0.10.1+cvs20060428
Import upstream version 0.10.1+cvs20060428

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This source code is public domain.
 
3
 *
 
4
 * Authors: Olivier Lapicque <olivierl@jps.net>
 
5
*/
 
6
 
 
7
#ifdef HAVE_CONFIG_H
 
8
#include "config.h"
 
9
#endif
 
10
 
 
11
#include "stdafx.h"
 
12
#include "sndfile.h"
 
13
 
 
14
//#pragma warning(disable:4244)
 
15
 
 
16
//////////////////////////////////////////////////////////
 
17
// MTM file support (import only)
 
18
 
 
19
#pragma pack(1)
 
20
 
 
21
 
 
22
typedef struct tagMTMSAMPLE
 
23
{
 
24
        char samplename[22];      // changed from CHAR
 
25
        DWORD length;
 
26
        DWORD reppos;
 
27
        DWORD repend;
 
28
        CHAR finetune;
 
29
        BYTE volume;
 
30
        BYTE attribute;
 
31
} MTMSAMPLE;
 
32
 
 
33
 
 
34
typedef struct tagMTMHEADER
 
35
{
 
36
        char id[4];             // MTM file marker + version // changed from CHAR
 
37
        char songname[20];      // ASCIIZ songname  // changed from CHAR
 
38
        WORD numtracks;         // number of tracks saved
 
39
        BYTE lastpattern;       // last pattern number saved
 
40
        BYTE lastorder;         // last order number to play (songlength-1)
 
41
        WORD commentsize;       // length of comment field
 
42
        BYTE numsamples;        // number of samples saved
 
43
        BYTE attribute;         // attribute byte (unused)
 
44
        BYTE beatspertrack;
 
45
        BYTE numchannels;       // number of channels used
 
46
        BYTE panpos[32];        // voice pan positions
 
47
} MTMHEADER;
 
48
 
 
49
 
 
50
#pragma pack()
 
51
 
 
52
 
 
53
BOOL CSoundFile::ReadMTM(LPCBYTE lpStream, DWORD dwMemLength)
 
54
//-----------------------------------------------------------
 
55
{
 
56
        MTMHEADER *pmh = (MTMHEADER *)lpStream;
 
57
        DWORD dwMemPos = 66;
 
58
 
 
59
        if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
 
60
        if ((strncmp(pmh->id, "MTM", 3)) || (pmh->numchannels > 32)
 
61
         || (pmh->numsamples >= MAX_SAMPLES) || (!pmh->numsamples)
 
62
         || (!pmh->numtracks) || (!pmh->numchannels)
 
63
         || (!pmh->lastpattern) || (pmh->lastpattern > MAX_PATTERNS)) return FALSE;
 
64
        strncpy(m_szNames[0], pmh->songname, 20);
 
65
        m_szNames[0][20] = 0;
 
66
        if (dwMemPos + 37*pmh->numsamples + 128 + 192*pmh->numtracks
 
67
         + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength) return FALSE;
 
68
        m_nType = MOD_TYPE_MTM;
 
69
        m_nSamples = pmh->numsamples;
 
70
        m_nChannels = pmh->numchannels;
 
71
        // Reading instruments
 
72
        for     (UINT i=1; i<=m_nSamples; i++)
 
73
        {
 
74
                MTMSAMPLE *pms = (MTMSAMPLE *)(lpStream + dwMemPos);
 
75
                strncpy(m_szNames[i], pms->samplename, 22);
 
76
                m_szNames[i][22] = 0;
 
77
                Ins[i].nVolume = pms->volume << 2;
 
78
                Ins[i].nGlobalVol = 64;
 
79
                DWORD len = pms->length;
 
80
                if ((len > 4) && (len <= MAX_SAMPLE_LENGTH))
 
81
                {
 
82
                        Ins[i].nLength = len;
 
83
                        Ins[i].nLoopStart = pms->reppos;
 
84
                        Ins[i].nLoopEnd = pms->repend;
 
85
                        if (Ins[i].nLoopEnd > Ins[i].nLength) Ins[i].nLoopEnd = Ins[i].nLength;
 
86
                        if (Ins[i].nLoopStart + 4 >= Ins[i].nLoopEnd) Ins[i].nLoopStart = Ins[i].nLoopEnd = 0;
 
87
                        if (Ins[i].nLoopEnd) Ins[i].uFlags |= CHN_LOOP;
 
88
                        Ins[i].nFineTune = MOD2XMFineTune(pms->finetune);
 
89
                        if (pms->attribute & 0x01)
 
90
                        {
 
91
                                Ins[i].uFlags |= CHN_16BIT;
 
92
                                Ins[i].nLength >>= 1;
 
93
                                Ins[i].nLoopStart >>= 1;
 
94
                                Ins[i].nLoopEnd >>= 1;
 
95
                        }
 
96
                        Ins[i].nPan = 128;
 
97
                }
 
98
                dwMemPos += 37;
 
99
        }
 
100
        // Setting Channel Pan Position
 
101
        for (UINT ich=0; ich<m_nChannels; ich++)
 
102
        {
 
103
                ChnSettings[ich].nPan = ((pmh->panpos[ich] & 0x0F) << 4) + 8;
 
104
                ChnSettings[ich].nVolume = 64;
 
105
        }
 
106
        // Reading pattern order
 
107
        memcpy(Order, lpStream + dwMemPos, pmh->lastorder+1);
 
108
        dwMemPos += 128;
 
109
        // Reading Patterns
 
110
        LPCBYTE pTracks = lpStream + dwMemPos;
 
111
        dwMemPos += 192 * pmh->numtracks;
 
112
        LPWORD pSeq = (LPWORD)(lpStream + dwMemPos);
 
113
        for (UINT pat=0; pat<=pmh->lastpattern; pat++)
 
114
        {
 
115
                PatternSize[pat] = 64;
 
116
                if ((Patterns[pat] = AllocatePattern(64, m_nChannels)) == NULL) break;
 
117
                for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < m_nChannels))
 
118
                {
 
119
                        LPCBYTE p = pTracks + 192 * (pSeq[n]-1);
 
120
                        MODCOMMAND *m = Patterns[pat] + n;
 
121
                        for (UINT i=0; i<64; i++, m+=m_nChannels, p+=3)
 
122
                        {
 
123
                                if (p[0] & 0xFC) m->note = (p[0] >> 2) + 37;
 
124
                                m->instr = ((p[0] & 0x03) << 4) | (p[1] >> 4);
 
125
                                UINT cmd = p[1] & 0x0F;
 
126
                                UINT param = p[2];
 
127
                                if (cmd == 0x0A)
 
128
                                {
 
129
                                        if (param & 0xF0) param &= 0xF0; else param &= 0x0F;
 
130
                                }
 
131
                                m->command = cmd;
 
132
                                m->param = param;
 
133
                                if ((cmd) || (param)) ConvertModCommand(m);
 
134
                        }
 
135
                }
 
136
                pSeq += 32;
 
137
        }
 
138
        dwMemPos += 64*(pmh->lastpattern+1);
 
139
        if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength))
 
140
        {
 
141
                UINT n = pmh->commentsize;
 
142
                m_lpszSongComments = new char[n+1];
 
143
                if (m_lpszSongComments)
 
144
                {
 
145
                        memcpy(m_lpszSongComments, lpStream+dwMemPos, n);
 
146
                        m_lpszSongComments[n] = 0;
 
147
                        for (UINT i=0; i<n; i++)
 
148
                        {
 
149
                                if (!m_lpszSongComments[i])
 
150
                                {
 
151
                                        m_lpszSongComments[i] = ((i+1) % 40) ? 0x20 : 0x0D;
 
152
                                }
 
153
                        }
 
154
                }
 
155
        }
 
156
        dwMemPos += pmh->commentsize;
 
157
        // Reading Samples
 
158
        for (UINT ismp=1; ismp<=m_nSamples; ismp++)
 
159
        {
 
160
                if (dwMemPos >= dwMemLength) break;
 
161
                dwMemPos += ReadSample(&Ins[ismp], (Ins[ismp].uFlags & CHN_16BIT) ? RS_PCM16U : RS_PCM8U,
 
162
                                                                (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
 
163
        }
 
164
        m_nMinPeriod = 64;
 
165
        m_nMaxPeriod = 32767;
 
166
        return TRUE;
 
167
}
 
168