1 /*
2 Copyright (c) 2009-2010 Tero Lindeman (kometbomb)
3
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use,
8 copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following
11 conditions:
12
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "export.h"
27 #include "gui/bevel.h"
28 #include "snd/cyd.h"
29 #include "macros.h"
30 #include "mused.h"
31 #include "gfx/gfx.h"
32 #include "gui/view.h"
33 #include "mybevdefs.h"
34 #include "gfx/font.h"
35 #include "theme.h"
36 #include <string.h>
37 #include "wavewriter.h"
38
39 extern GfxDomain *domain;
40
export_wav(MusSong * song,CydWavetableEntry * entry,FILE * f,int channel)41 bool export_wav(MusSong *song, CydWavetableEntry * entry, FILE *f, int channel)
42 {
43 bool success = false;
44
45 MusEngine mus;
46 CydEngine cyd;
47
48 cyd_init(&cyd, 44100, MUS_MAX_CHANNELS);
49 cyd.flags |= CYD_SINGLE_THREAD;
50 mus_init_engine(&mus, &cyd);
51 mus.volume = song->master_volume;
52 mus_set_fx(&mus, song);
53 CydWavetableEntry * prev_entry = cyd.wavetable_entries; // save entries so they can be free'd
54 cyd.wavetable_entries = entry;
55 cyd_set_callback(&cyd, mus_advance_tick, &mus, song->song_rate);
56 mus_set_song(&mus, song, 0);
57 song->flags |= MUS_NO_REPEAT;
58
59 if (channel >= 0)
60 {
61 // if channel is positive then only export that channel (mute other chans)
62
63 for (int i = 0 ; i < MUS_MAX_CHANNELS ; ++i)
64 mus.channel[i].flags |= MUS_CHN_DISABLED;
65
66 mus.channel[channel].flags &= ~MUS_CHN_DISABLED;
67 }
68 else
69 {
70 for (int i = 0 ; i < MUS_MAX_CHANNELS ; ++i)
71 mus.channel[i].flags &= ~MUS_CHN_DISABLED;
72 }
73
74 const int channels = 2;
75 Sint16 buffer[2000 * channels];
76
77 int last_percentage = -1;
78
79 WaveWriter *ww = ww_create(f, cyd.sample_rate, 2);
80
81 for (;;)
82 {
83 memset(buffer, 0, sizeof(buffer)); // Zero the input to cyd
84 cyd_output_buffer_stereo(&cyd, (Uint8*)buffer, sizeof(buffer));
85
86 if (cyd.samples_output > 0)
87 ww_write(ww, buffer, cyd.samples_output);
88
89 if (mus.song_position >= song->song_length) break;
90
91 if (song->song_length != 0)
92 {
93 int percentage = (mus.song_position + (channel == -1 ? 0 : (channel * song->song_length))) * 100 / (song->song_length * (channel == -1 ? 1 : song->num_channels));
94
95 if (percentage > last_percentage)
96 {
97 last_percentage = percentage;
98
99 SDL_Rect area = {domain->screen_w / 2 - 140, domain->screen_h / 2 - 24, 280, 48};
100 bevel(domain, &area, mused.slider_bevel, BEV_MENU);
101
102 adjust_rect(&area, 8);
103 area.h = 16;
104
105 bevel(domain, &area, mused.slider_bevel, BEV_FIELD);
106
107 adjust_rect(&area, 2);
108
109 int t = area.w;
110 area.w = area.w * percentage / 100;
111
112 gfx_rect(domain, &area, colors[COLOR_PROGRESS_BAR]);
113
114 area.y += 16 + 4 + 4;
115 area.w = t;
116
117 font_write_args(&mused.smallfont, domain, &area, "Exporting... Press ESC to abort.");
118
119 SDL_Event e;
120
121 while (SDL_PollEvent(&e))
122 {
123 if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE))
124 {
125 goto abort;
126 }
127 }
128
129 gfx_domain_flip(domain);
130 }
131 }
132 }
133
134 success = true;
135
136 abort:;
137
138 ww_finish(ww);
139
140 cyd.wavetable_entries = prev_entry;
141
142 cyd_deinit(&cyd);
143
144 song->flags &= ~MUS_NO_REPEAT;
145
146 return success;
147 }
148
149