This thesis presents a general-purpose software defined radio architecture, Surfer, which has been designed to allow for dynamic modification of system behavior during runtime. Surfer leverages commodity processing devices such as those on a typical laptop to allow heterogeneous processing. This heterogeneity is enabled through the use of one or more signal processing implementations, or flavors, per block. Each flavor can target a different processing device, and flavors can be swapped during runtime without interrupting data flow. Two waveform programming interfaces are provided that can be intermixed for waveform definition: traditional block-centric programming, and a buffer-centric approach such as that found in MATLAB. Within a waveform graph consisting of processing blocks, each connection is a buffer that holds the data being generated by one block and consumed by others. Each connection is paired with a threshold on the amount of data in the buffer, and is used for scheduling. Runtime statistics allow a system supervisor to assist in mapping and scheduling, dynamically during runtime, in order to meet waveform requirements. This work demonstrates that it is both possible and useful to implement dynamic reconfiguration, mapping, and scheduling during runtime on commodity hardware, entirely in software. These capabilities are demonstrated via an OFDM transmitter implementation.