git.haldean.org qb / e8b3d6b
playback!! haldean 5 months ago
2 changed file(s) with 35 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
2222 qb::theme::setdefault();
2323 }
2424
25 int context::frame2pixel(int frame) {
25 int context::frame2pixel(double frame) {
2626 const double off = frame - playhead;
2727 const double ndc = off / (double)visrad;
2828 const int px = (int) round(width * (ndc + 1) / 2.0);
4848 initaudio();
4949 }
5050 if (audioinit) {
51 if (ImGui::IsKeyPressed(SAPP_KEYCODE_SPACE, /* repeat */ false)) {
52 playing = !playing;
53 }
5154 pushaudio();
5255 }
5356
6063
6164 if (ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
6265 const ImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Middle);
63 const bool horiz = abs(delta.x) > abs(delta.y);
66 const bool horiz = !playing && abs(delta.x) > abs(delta.y);
6467 const double pxperframe = width / (2.0 * std::max(visrad, 1.0));
6568 const double framedist = horiz ? 0.1 * delta.x / pxperframe : 0;
6669 const double zoomdist = !horiz ? 0.1 * delta.y / pxperframe : 0;
7174 // draw playhead
7275 {
7376 ImDrawList * const drawlist = ImGui::GetWindowDrawList();
74 const float f0x = (float) frame2pixel((int) playhead);
75 const float f1x = (float) frame2pixel((int) playhead + 1);
77 const float f0x = (float) frame2pixel(playhead);
78 const float f1x = (float) frame2pixel(playhead + 1);
7679 if (f1x > 0 && f1x != f0x) {
7780 drawlist->AddRectFilled(ImVec2(f0x, 0.0), ImVec2(f1x, (float) height),
7881 qb::theme::colors[qb::theme::color::playhead]);
111114 saudio_desc d = {0};
112115 d.sample_rate = audiosource->data()->getSampleRate();
113116 d.num_channels = audiosource->data()->getNumChannels();
114 //d.buffer_frames = 4 * d.sample_rate / _framerate;
115117
116118 saudio_setup(&d);
117119 audioinit = saudio_isvalid();
125127 if (!audiosource) {
126128 return;
127129 }
130
131 const int samplerate = audiosource->data()->getSampleRate();
132 const double sampleperframe = (double) samplerate / (double) _framerate;
133
128134 if (!playing) {
129135 if ((int) playhead == playedframe) {
130136 return;
131137 }
132 const int samplerate = audiosource->data()->getSampleRate();
133 const double sampleperframe = (double) samplerate / (double) _framerate;
134138 const double firstsample = floor(playhead) * sampleperframe;
135139 const size_t s0 = (size_t) floor(firstsample);
136140
137141 const int topush = (int) sampleperframe;
138142 const int pushed =
139143 saudio_push(&audiosource->packed()[s0], topush);
140 if (pushed != topush) {
141 printf("tried to push %d at offset %zu, pushed %d\n", topush, s0, pushed);
142 }
143144 playedframe = (int) playhead;
145 pushedsample = (int64_t) (s0 + sampleperframe - 1);
146
147 } else {
148
149 const double elapsed = ImGui::GetIO().DeltaTime;
150 playhead += elapsed * _framerate;
151
152 const int64_t nextsample = (int64_t) floor(playhead * sampleperframe);
153
154 // buffer 125ms of audio
155 const int buffersamples = samplerate / 8;
156 // add to buffer whenever we have less than 50ms left in the buffer
157 const int bufferrefill = samplerate / 20;
158
159 if (pushedsample < 0) {
160 int pushed = saudio_push(&audiosource->packed()[nextsample], buffersamples);
161 pushedsample = nextsample + pushed;
162 } else if (pushedsample - nextsample < bufferrefill) {
163 int pushed = saudio_push(&audiosource->packed()[pushedsample + 1], buffersamples);
164 pushedsample += pushed;
165 }
144166 }
145167 }
146168
103103 void frame(int width, int height);
104104 void shutdown();
105105
106 int frame2pixel(int frame);
107 int pixel2frame(int frame);
106 int frame2pixel(double frame);
108107
109108 bool playing = false;
110109
122121
123122 bool audioinit = false;
124123 int playedframe = -1;
124 int64_t pushedsample = -1;
125
125126 const audio_node *audiosource = nullptr;
126127
127128 int _framerate = 24;