This is the route I’d go. I use FreePBX for all this, but my voip provider could do most of the work (voip.ms). There are decent softphone apps (Zoiper, Linphone, etc.) to initiate calls from and porting a number to the voip provider isn’t too difficult.